First function changes big letter to small. In main I need to have five strings and with function konvertuj
I have to go through that array and check for each letter if it's big and convert it to small. The point is that I don't know how to access each character of string in the function. (It's study example so it has to be done with these predefined functions.
char v2m(char z){
char m = z + 0x20;
return m;
}
void konvertuj(char **niz, int n){
for (int i = 0; i < n; i++)
if(*niz[i] > 'A' && *niz[i] < 'Z')
*niz[i] = v2m(*niz[i]);
}
int main(){
char **niz;
niz[0] = "Voda";
niz[1] = "KraISSa";
niz[2] = "somsssR";
niz[3] = "aaaaa";
niz[4] = "WeWeWeW";
for (int i = 0; i < 5; i++)
{
int d = -1;
while(niz[i][++d]);
konvertuj(&niz[i], d);
printf("%s ", niz[i]);
}
}
v2m
- no need of the variable m
konvertuj
no need to iterate through the same letters all over again. You want to convert 1 letter as you iterate in main
. Your condition is wrong as you will ignore 'A'
and 'Z'
Pointer to pointer does not have allocated space to accommodate 5 pointers. You need to allocate this space. In your code is it UB.
3.a You assign the pointers to the string literals. Attempt to modify the string literal invokes Undefined Behaviour. In my code, I use compound literals which are modifiable.
3.b use correct type for indexes ( size_t
).
char v2m(char z){
return z + 0x20;
}
void konvertuj(char *niz, size_t n){
if(niz[n] >= 'A' && niz[n] <= 'Z')
niz[n] = v2m(niz[n]);
}
int main(void){
char **niz = malloc(5 * sizeof((*niz)));
niz[0] = (char[]){"Voda"};
niz[1] = (char[]){"KraISSa"};
niz[2] = (char[]){"somsssR"};
niz[3] = (char[]){"aaaaa"};
niz[4] = (char[]){"WeWeWeW"};
for (size_t i = 0; i < 5; i++)
{
size_t d = 0;
while(niz[i][d])
konvertuj(niz[i], d++);
printf("%s ", niz[i]);
}
}
As I( understand you need to keep the function names types and parameters
Sure, it is possible to write it the way you did, but you have to build things accordingly and you did not.
And there some errors, anyway. I will try to show you some points. Please be patient.
niz[0] = "Voda";
niz[1] = "KraISSa";
niz[2] = "somsssR";
niz[3] = "aaaaa";
niz[4] = "WeWeWeW";
In C in general you can not just assign a value to a string. You use something like
strcpy( niz[0], "ANewValue");
Instead of
char v2m(char z){
char m = z + 0x20;
return m;
}
You can just write
char v2m(char z) { return z + 0x20; }
There is no need to declare a char just for holding the return value.
IIUC you can not change the function prototypes...
void konvertuj(char **niz, int n){
for (int i = 0; i < n; i++)
if(*niz[i] > 'A' && *niz[i] < 'Z')
*niz[i] = v2m(*niz[i]);
}
here I believe you missed the point that the function will receive just a string each time is called, not the whole vector of strings.
The int n
is just the length of the string, and even if you could not use strlen()
to compute it, it should probably be done inside the function. but I believe you can not change this prototype also.
This one below should work and you can compare:
void konvertuj(char *niz, int n)
{
for (int i = 0; i < n; i++)
if(niz[i] >= 'A' && niz[i] <= 'Z')
niz[i] = v2m(niz[i]);
}
Instead of
char **niz;
niz[0] = "Voda";
niz[1] = "KraISSa";
niz[2] = "somsssR";
niz[3] = "aaaaa";
niz[4] = "WeWeWeW";
You could write just
char niz[][15] =
{
"Voda",
"KraISSa",
"somsssR",
"aaaaa",
"WeWeWeW"
};
In C just the last dimension must be declared, eg the '15' above, since the compiler can determine here the other dimension. And this way you can initialize all of them directly. But in order to change one in the code you need to use a loop and replace letter by letter, or call
strcpy( niz[0], "ANewValue");
Also you can initialize just a few of them, and even out of order, as in
char niz[8][15] =
{
[2] = "somsssR",
[3] = "aaaaa",
[5] = "AomsssZ",
[6] = "A",
[0] = "Voda",
[1] = "KraISSa",
[4] = "WeWeWeW",
[7] = ""
};
and this is really handy.
Note that you can compute the number of strings and even assign "TheLastValue" to the last one, by writing
int n = sizeof(niz)/sizeof(niz[0]); // total of strings
strcpy( niz[n-1], "TheLastValue"); // changes the last string
printf("Total of %llu values\n", sizeof(niz)/sizeof(niz[0]));
char** niz
is needed?This is a really common paradigm in C and C++, and it is very useful. You may recall that the prototype for main() is
int main( int argc, char** argc)
for every C program, so you can see how common it is.
Fact is that when you declare niz
as char**
you are declaring a single variable. What is niz? Well, it is a pointer to a pointer to a char.
niz
is char**
*niz
is char*
**niz
is a single char
But niz
is a pointer and it is pointing to nowhere when declared. In your case you want niz
pointing to not one but FIVE strings. And if you do nothing the program will abort the first time you try to use it...
You need to build this:
A string is a pointer to the first char
, char*
niz
needs to point to an area capable of holding 5 pointers to char
char
? That is easy: sizeof(char*)
niz[x]
point to the required string.char** sample
from niz
as declared above The code below builds sample
as an array of pointers, pointing to the same strings declared and allocated for niz[][]
above, and them prints them all
// building an array of pointers to the strings in niz
char** sample = NULL; // ok, points to nothing
unsigned area = n * sizeof(char*); // n pointers to strings
sample = (char**) malloc(area);
for( int i=0; i<n; i+=1)
sample[i] = niz[i];
printf("\n=>\tPrinting the %d strings using the pointers\n", n );
for( int i=0; i<n; i+=1)
printf("%2d: '%s'\n", i, sample[i]);
Note that the strings already exists and we are just pointing to them. A new reference only.
char** copy
as a full copy of niz
It is very very important to see the difference here: copy
points to an array of pointers, but each pointer points to a copy of the corresponding string declared in niz
and referenced in the sample
array.
// building 'copy' as an array of pointers to the strings once in niz
char** copy = NULL; // ok, points to nothing
copy = (char**) malloc(area);
for( int i=0; i<n; i+=1)
{
copy[i] = (char*) malloc( (1 + sizeof(niz[i])) * sizeof(char) );
// large enough to hold it
int j = 0; // copy each letter
for ( ; niz[i][j] != 0; j+=1 ) copy[i][j] = niz[i][j];
copy[i][j] = 0; // this terminates the string
}
printf("\n=>\tPrinting the %d copies using the pointers\n", n );
for( int i=0; i<n; i+=1)
printf("%2d: '%s'\n", i, copy[i]);
Note: it is in general not recommended to cast the pointers return by malloc() in C, as in the lines
copy = (char**) malloc(area);
// or
copy[i] = (char*) malloc( (1 + sizeof(niz[i])) * sizeof(char) );
I just do not care and prefer to write all them down explicitly, as a reminder to myself of what is what. Sure, in C++ you must declare this, but is is rare to allocate memory this way in C++ since C++11. Fell free to use whatever rule you see fit
This is the output
PS C:\src\ifdef> gcc -o teste -Wall -Wextra -Wpedantic -std=c17 so210126.c
PS C:\src\ifdef> ./teste
Total of 8 values
Before: Voda (4)
After: voda
Before: KraISSa (7)
After: kraissa
Before: somsssR (7)
After: somsssr
Before: aaaaa (5)
After: aaaaa
Before: WeWeWeW (7)
After: wewewew
Before: AomsssZ (7)
After: aomsssz
Before: A (1)
After: a
Before: TheLastValue (12)
After: thelastvalue
=> Printing the 8 strings using the pointers
0: 'voda'
1: 'kraissa'
2: 'somsssr'
3: 'aaaaa'
4: 'wewewew'
5: 'aomsssz'
6: 'a'
7: 'thelastvalue'
=> Printing the 8 copies using the pointers
0: 'voda'
1: 'kraissa'
2: 'somsssr'
3: 'aaaaa'
4: 'wewewew'
5: 'aomsssz'
6: 'a'
7: 'thelastvalue'
PS C:\src\ifdef>
I compiled just on gcc 10.2 on Windows.
This is the example code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char v2m(char z) { return z + 0x20; }
void konvertuj(char *niz, int n)
{
for (int i = 0; i < n; i++)
if(niz[i] >= 'A' && niz[i] <= 'Z')
niz[i] = v2m(niz[i]);
}
int main(void)
{
char niz[8][15] =
{
[2] = "somsssR",
[3] = "aaaaa",
[5] = "AomsssZ",
[6] = "A",
[0] = "Voda",
[1] = "KraISSa",
[4] = "WeWeWeW",
[7] = ""
};
int n = sizeof(niz)/sizeof(niz[0]); // total of strings
strcpy( niz[n-1], "TheLastValue"); // changes the last string
printf("Total of %llu values\n", sizeof(niz)/sizeof(niz[0]));
for (int i = 0; i < n; i++)
{
int d = 0;
while ( niz[i][d] != 0) d+=1;
printf("Before: %s (%d)\n", niz[i], d);
konvertuj( niz[i], d );
printf("After: %s\n", niz[i]);
}
// building an array of pointers to the strings in niz
char** sample = NULL; // ok, points to nothing
unsigned area = n * sizeof(char*); // n pointers to strings
sample = (char**) malloc(area);
for( int i=0; i<n; i+=1)
sample[i] = niz[i];
printf("\n=>\tPrinting the %d strings using the pointers\n", n );
for( int i=0; i<n; i+=1)
printf("%2d: '%s'\n", i, sample[i]);
// building 'copy' as an array of pointers to the strings once in niz
char** copy = NULL; // ok, points to nothing
copy = (char**) malloc(area);
for( int i=0; i<n; i+=1)
{
copy[i] = (char*) malloc( (1 + sizeof(niz[i])) * sizeof(char) ); // large enough to hold it
int j = 0; // copy each letter
for ( ; niz[i][j] != 0; j+=1 ) copy[i][j] = niz[i][j];
copy[i][j] = 0; // this terminates the string
}
printf("\n=>\tPrinting the %d copies using the pointers\n", n );
for( int i=0; i<n; i+=1)
printf("%2d: '%s'\n", i, copy[i]);
for( int i=0; i<n; i+=1) free(copy[i]); // destroy each string
free(copy); // destroy the array;
free(sample); // sample points to static memory...
return 0;
}
As for the very very long post: I wanted to leave an example of the solution plus an example of the steps involved in order to build a
char**
vector from existing strings and as an independend copy.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.