I'm trying to create a program which takes in a set number of strings (the user is asked to put in the number of strings they will enter), once it has these strings, they are placed in an array, using dynamic memory.
The ouput would be something like this:
# of Strings: 3
Cat
Dog
Elephant
Cat
Dog
Elephant
Heres a snippet of my code, after I have the number of strings.
sptr=malloc(sizeof(char*)*nStrings);
for(i=0;i<nStrings;i++)
{
scanf("%s",string);
length=strlen(string);
sptr[i]=malloc(sizeof(char)*length);
sptr[i]=string;
}
Where sptr is the array I'll access to output the strings.
So it's an array of pointers which then point to individual strings (or other arrays of characters, if you'd prefer to think of it that way).
Lets say there are two strings.
I allocate memory for two pointers,
Then in the first pointer, i scan in a string,
i find the length of the string,
i allocate memory the size of the string
and i equal the pointer to the string.
This all works dandy, and if I were to put a printf() right after that last line, it will work.
The problem i face is, if lets say there are 3 strings, each time through sptr[i] is assigned correctly, but then outside of that block, all of the indicies of sptr are = to the last string i put in, and I have no idea why.
If you could help me out I'd appreciate it. Thanks.
sptr=malloc(sizeof(char*)*nStrings);
for(i=0;i<nStrings;i++)
{
scanf("%s",string);
sptr[i]=strdup(string);
}
I assume the variable string has enough memory to keep the read strings.
The error occured because you set the pointer to point to the string variable.
You need to allocate 1 character extra for the null terminator:
sptr[i]=malloc(sizeof(char)*(length+1));
Also, you need to copy the string into the newly allocated memory:
strcpy(sptr[i], string);
There are 2 problems in your code: you don't allocate enough memory. Should be length + 1 because of the ending \0 in a string. Secondly you should use strcpy to copy the string to your allocated memory. Lookup the strdup function that handles both.
strlen doesn't account for the zero termination, you need to add one. But mainly you need to copy the string into the memory you allocate.
Related
The code is as follows:
char seg1[] = "abcdefgh";
char seg2[] = "ijklmnop";
char seg3[] = "qrstuvwx";
strcat(seg2, seg3);
Then the value stored in seg1 will become:
"rstuvwx\0\0"
I have learned to declare that strings with close positions are also adjacent in the stack area, but I forgot the details.
I guess the memory address of seg1 was overwritten when strcat() was executed, but I'm not sure about the specific process. Can someone tell me the specific process of this event?Thanks
C does not have a string class, it has character arrays which may be used as strings by appending a null terminator. And since there is no string class, all memory management of strings/arrays must be done manually.
char seg1[] = "abcdefgh"; Allocates space for exactly 8 characters and 1 null terminator. There is no room to append anything else at the end. If you try anyway, that's the realm of undefined behavior, where anything can happen. Crashes, overwriting other variables, program ceasing to function as expected and so on.
Solve this by allocating enough space to append something in the end, for example
char seg1[50] = "abcdefgh";. Alternatively allocate a new, third array and copy the strings into that one.
this is my problem... I created an array of strings like this..
char *name[12];
Then the user types 12 different names so I can save them in that array. But it is known that if you don't initialize a variable it has 'garbage' in it. So I started saving the names correctly until the 5th name, then it crashes, I don't know why. So I tried to initialize every element but then it doesn't allow me to change the content.
This is how I write into every element of the array:
printf("Type your name: ");
fflush(stdin);
gets( name[0] ); //I use a for to move into every element
And I want to know if there's any way to initialize the array, and to change it's content after that. I've tried with strcpy(); but I had the same error. Or how to delete that 'garbage' to stop it from causing me errors.
Thanks, and sorry if I had any misspelling. English is not my native language.
You've allocated space for 12 pointers; you've never allocated the space for the 12 strings, let alone assigned the pointers to that space to the pointers in the array.
The problem is that you have your array of char pointers, but you haven't initialised them or allocated space for them in any way. So you don't know what will happen when you use the address it points to.
You would have to loop through the array and initialise the elements before you can use them.
name[0] = malloc (SIZE);
You can try reading user input to a buffer to get the length of the data entered, then mallocating just the correct amount of space, or having a pre-defined chunk of memory to allocate before using it.
I need to find if a char array starts with "ADD". I know to use strcmp(), but I don't know how to get the first three characters. I really hate working with c-strings. How can I take a slice of a char array like char buffer[1024]?
Use strncmp("ADD", buffer, 3).
I am not sure what you mean by “slice” but any pointer inside buffer could be considered a slice. For example if buffer is a string that starts with "ADD" then char *slice = buffer + 3 is the same string with "ADD" removed. Note that slice is then a part of buffer and modifying the content of the slice will modify the content of the buffer. And the other way round.
If by “slice” you mean an independant copy then you have to allocate a new memory block and copy the interesting parts from buffer to your memory. The library functions strdup and strndup are handy for this.
Use strncmp.Assuming buffer is the variable to test, just
strncmp (buffer,"ADD",3);
I'm fairly new to the concept of pointers in C. Let's say I have two variables:
char *arch_file_name;
char *tmp_arch_file_name;
Now, I want to copy the value of arch_file_name to tmp_arch_file_name and add the word "tmp" to the end of it. I'm looking at them as strings, so I have:
strcpy(&tmp_arch_file_name, &arch_file_name);
strcat(tmp_arch_file_name, "tmp");
However, when strcat() is called, both of the variables change and are the same. I want one of them to change and the other to stay intact. I have to use pointers because I use the names later for the fopen(), rename() and delete() functions. How can I achieve this?
What you want is:
strcpy(tmp_arch_file_name, arch_file_name);
strcat(tmp_arch_file_name, "tmp");
You are just copying the pointers (and other random bits until you hit a 0 byte) in the original code, that's why they end up the same.
As shinkou correctly notes, make sure tmp_arch_file_name points to a buffer of sufficient size (it's not clear if you're doing this in your code). Simplest way is to do something like:
char buffer[256];
char* tmp_arch_file_name = buffer;
Before you use pointers, you need to allocate memory. Assuming that arch_file_name is assigned a value already, you should calculate the length of the result string, allocate memory, do strcpy, and then strcat, like this:
char *arch_file_name = "/temp/my.arch";
// Add lengths of the two strings together; add one for the \0 terminator:
char * tmp_arch_file_name = malloc((strlen(arch_file_name)+strlen("tmp")+1)*sizeof(char));
strcpy(tmp_arch_file_name, arch_file_name);
// ^ this and this ^ are pointers already; no ampersands!
strcat(tmp_arch_file_name, "tmp");
// use tmp_arch_file_name, and then...
free(tmp_arch_file_name);
First, you need to make sure those pointers actually point to valid memory. As they are, they're either NULL pointers or arbitrary values, neither of which will work very well:
char *arch_file_name = "somestring";
char tmp_arch_file_name[100]; // or malloc
Then you cpy and cat, but with the pointers, not pointers-to-the-pointers that you currently have:
strcpy (tmp_arch_file_name, arch_file_name); // i.e., no "&" chars
strcat (tmp_arch_file_name, "tmp");
Note that there is no bounds checking going on in this code - the sample doesn't need it since it's clear that all the strings will fit in the allocated buffers.
However, unless you totally control the data, a more robust solution would check sizes before blindly copying or appending. Since it's not directly related to the question, I won't add it in here, but it's something to be aware of.
The & operator is the address-of operator, that is it returns the address of a variable. However using it on a pointer returns the address of where the pointer is stored, not what it points to.
If I have a character pointer that contains NULL bytes is there any built in function I can use to find the length or will I just have to write my own function? Btw I'm using gcc.
EDIT:
Should have mentioned the character pointer was created using malloc().
If you have a pointer then the ONLY way to know the size is to store the size separately or have a unique value which terminates the string. (typically '\0') If you have neither of these, it simply cannot be done.
EDIT: since you have specified that you allocated the buffer using malloc then the answer is the paragraph above. You need to either remember how much you allocated with malloc or simply have a terminating value.
If you happen to have an array (like: char s[] = "hello\0world";) then you could resort to sizeof(s). But be very careful, the moment you try it with a pointer, you will get the size of the pointer, not the size of an array. (but strlen(s) would equal 5 since it counts up to the first '\0').
In addition, arrays decay to pointers when passed to functions. So if you pass the array to a function, you are back to square one.
NOTE:
void f(int *p) {}
and
void f(int p[]) {}
and
void f(int p[10]) {}
are all the same. In all 3 versions, p is a pointer, not an array.
How do you know where the string ends, if it contains NULL bytes as part of it? Certainly no built in function can work with strings like that. It'll interpret the first null byte as the end of the string.
If you want the length, you'll have to store it yourself. Keep in mind that no standard library string functions will work correctly on strings like these.
You'll need to keep track of the length yourself.
C strings are null terminated, meaning that the first null character signals the end of the string. All builtin string functions rely on this, so if you have a buffer that can contain NULLs as part of the data then you can't use them.
Since you're using malloc then you may need to keep track of two sizes: the size of your allocated buffer, and how many characters within that buffer constitute valid data.