For the following code, I added two printf statements to test if the two strings are read properly. However, when I enter something like: abcabcabcza,cb
The outputs are:
abcabcabcza▒
cb9
Does anyone know where the symbol at the end of the first string, and the '9' at the end of the second string, come from? Thank you so much!
printf("\nEnter two words, seperated by a comma: ");
int temp1, temp2, index3, index4; char temp3[20], temp4[20];
index3=index4=0;
while((temp1 = getchar())!= ','){
temp3[index3++] = temp1;
}
printf("\n%s", temp3);
while((temp2 = getchar())!= '\n'){
temp4[index4++] = temp2;
}
printf("\n%s", temp4);
You need to add string terminators '\0' to your string before printing (or zero out the buffers memory first).
Also: you have declared buffers of size 20, but have no guards in your code to respect that allocated length, which means you could overrun them and corrupt memory. [Run with two words greater than 20 characters...]
'\n' and '\0' are different here. You need to add '\0' at the end of string because printf prints out string until it meets '\0'. C doesn't initializes array. If you do not initialize manually it will have garbage values.
I would do:
char temp3[20] = {0};
char temp4[20] = {0};
to fill out temp3 and temp3 with 0, which is same as '\0'.
when you give a string as 'abc' it will be saved as 'abc\0',so check for \0 also and dont print it
The string in C requires to be NULL-terminated.
A lot of functions use that terminator to announce the processor where the string ends.
What will hapan if not terminated? Lets get one simple string, with consumpption of 5 bytes of memory.
...[?][?][H][e][l][l][o][?][?][?]...
That causes a leak. As you see we haven't store a NULL. It causes u/b and you may get different signs on any new run. For us.. the processor puts the string in random blocks of memory. However gcc by default has optimizations to prevent that.
Related
i got a string and a scanf that reads from input until it finds a *, which is the character i picked for the end of the text. After the * all the remaining cells get filled with random characters.
I know that a string after the \0 character if not filled completly until the last cell will fill all the remaining empty ones with \0, why is this not the case and how can i make it so that after the last letter given in input all the remaining cells are the same value?
char string1 [100];
scanf("%[^*]s", string1);
for (int i = 0; i < 100; ++i) {
printf("\n %d=%d",i,string1[i]);
}
if i try to input something like hello*, here's the output:
0=104
1=101
2=108
3=108
4=111
5=0
6=0
7=0
8=92
9=0
10=68
You have an uninitialized array:
char string1 [100];
that has indeterminate values. You could initialize the array like
char string1 [100] = { 0 };
or
char string1 [100] = "";
In this call
scanf("%[^*]s", string1);
you need to remove the trailing character s, because %[] and %s are distinct format specifiers. There is no %[]s format specifier. It should look like this:
scanf("%[^*]", string1);
The array contains a string terminated by the zero character '\0'.
So to output the string you should write for example
for ( int i = 0; string1[i] != '\0'; ++i) {
printf( "%c", string1[i] ); // or putchar( string1[i] );
putchar( '\n' );
or like
for ( int i = 0; string1[i] != '\0'; ++i) {
printf("\n %d=%c",i,string1[i]);
putchar( '\n' );
or just
puts( string1 );
As for your statement
printf("\n %d=%d",i,string1[i]);
then it outputs each character (including non-initialized characters) as integers due to using the conversion specifier d instead of c. That is the function outputs internal ASCII representations of characters.
I know that a string after the \0 character if not filled completly
until the last cell will fill all the remaining empty ones with \0
No, that's not true.
It couldn't be true: there is no length to a string. No where neither the compiler nor any function can even know what is the size of the string. Only you do. So, no, string don't autofill with '\0'
Keep in minds that there aren't any string types in C. Just pointer to chars (sometimes those pointers are constant pointers to an array, but still, they are just pointers. We know where they start, but there is no way (other than deciding it and being consistent while coding) to know where they stop.
Sure, most of the time, there is an obvious answer, that make obvious for any reader of the code what is the size of the allocated memory.
For example, when you code
char string1[20];
sprintf(string1, "hello");
it is quite obvious for a reader of that code that the allocated memory is 20 bytes. So you may think that the compiler should know, when sprinting in it of sscaning to it, that it should fill the unused part of the 20 bytes with 0. But, first of all, the compiler is not there anymore when you will sscanf or sprintf. That occurs at runtime, and compiler is at compilation time. At run time, there is not trace of that 20.
Plus, it can be more complicated than that
void fillString(char *p){
sprintf(p, "hello");
}
int main(){
char string1[20];
string1[0]='O';
string1[1]='t';
fillString(&(string1[2]));
}
How in this case does sprintf is supposed to know that it must fill 18 bytes with the string then '\0'?
And that is for normal usage. I haven't started yet with convoluted but legal usages. Such as using char buffer[1000]; as an array of 50 length-20 strings (buffer, buffer+20, buffer+40, ...) or things like
union {
char str[40];
struct {
char substr1[20];
char substr2[20];
} s;
}
So, no, strings are not filled up with '\0'. That is not the case. It is not the habit in C to have implicit thing happening under the hood. And that could not be the case, even if we wanted to.
Your "star-terminated string" behaves exactly as a "null-terminated string" does. Sometimes the rest of the allocated memory is full of 0, sometimes it is not. The scanf won't touch anything else that what is strictly needed. The rest of the allocated memory remains untouched. If that memory happened to be full of '\0' before the call to scanf, then it remains so. Otherwise not. Which leads me to my last remark: you seem to believe that it is scanf that fills the memory with non-null chars. It is not. Those chars were already there before. If you had the feeling that some other methods fill the rest of memory with '\0', that was just an impression (a natural one, since most of the time, newly allocated memory are 0. Not because a rule says so. But because that is the most frequent byte to be found in random area of memory. That is why uninitialized variables bugs are so painful: they occur only from times to times, because very often uninitialized variables are 0, just by chance, but still they are)
The easiest way to create a zeroed array is to use calloc.
Try replacing
char string1 [100];
with
char *string1=calloc(1,100);
I am trying to understand string's behavior in C and it is bothering me since my following two code snippets result into different output:
(For the sake of this question, Let us assume user enters 12)
int main(void)
{
char L_Red[2];
char temp[] = "I";
printf("Enter pin connected to red: ");
scanf("%s", L_Red);
strcat(temp,L_Red);
printf("%s \n", temp);
return 0;
}
this yields: 12 as output (and not I12) Why ?
int main(void)
{
char L_Red[2];
printf("Enter pin connected to red: ");
scanf("%s", L_Red);
char temp[] = "I";
strcat(temp,L_Red);
printf("%s \n", temp);
return 0;
}
This yields: I12I (and not, I12) Why ?
I have read about string in C and as per my understanding, neither am I allocating temp any fixed size and changing it later to get these vague outputs nor am I using strings like the way they are not supposed to. Is there any other concept at play here ?
The array temp is an array of two characters (the 'I' and the string terminator '\0'). That's it. Attempting to append more characters to that array will write out of bounds and lead to undefined behavior.
You need to make sure that the destination array temp have enough space to fit its original content plus the string you want to append (plus the terminator).
Also, if you want to input more than one character for the "string" L_Red you need to increase its size as well.
I also recommend you use a limit in the format specifier so you can't write out of bounds:
char L_Red[3]; // Space for two characters, plus terminator
scanf("%2s", L_Red); // Read at most two characters of input
You are getting strange answers because your destination string (ie the first argument to strcat) is not long enough to handle both strings plus a null termination character. Also the length of L_Red is too short as it does not have enough space for the null termination character either.
I wrote a code for scanning a string from user using pointers and storing it in another string array and printing that string array. The output is coming quite strange. The first three characters are printed but next characters are coming as random garbage values. Please tell me the error in the code. Following is the code:
#include<stdio.h>
int main(void)
{
char str1[8];
char *p1=str1;
char str2[8];
char *p2=str2;
printf("Enter a string\n");
while(*p1)
scanf("%c",p1++);
*p1='\0';
p1=&str1[0];
while(*p1)
*p2++=*p1++;
*p2='\0';
printf("The copied string is :");
p2=&str2[0];
while(*p2)
printf("%c",*p2++);
}
You are not placing the terminating null character('\0') at the end of your strings str1[] and str2[]. And you are trying to dereference and check the value which is not initialized in your first while loop condition: while(*p1)
printf("Enter a string\n");
do{
scanf("%c",p1++);
}while(*(p1 - 1) != '\n'); //try the do while loop
*(p1 - 1) = '\0'; //placing terminating null character
p1 = &str1[0];
while(*p1){
*p2++ = *p1++;
}
*p2 = '\0'; //placing terminating null character
here's the demo code: https://ideone.com/dF2QsJ
Why have you checked the condition for the new line in the do while condition? And why p1-1?
This is because you end the input by entering a '\n' which gets stored at p1 and then p1 moves to p1 + 1 at the end of each iteration. So, I check whether a '\n' is present at p1 - 1.
okay,
Why arent you using %s and get the input directly. you can get the entire string rather than looping over each character.
This loop
while(*p1)
scanf("%c",p1++);
checks the contents of str1 (pointed at by p1) before ever storing anything there. That uninitialized memory might contain anything, so this loop might never execute (if the first char happens to be NUL), or might run off the end of the array (corrupting memory).
I'm trying to tokenize a phone number and split it into two arrays. It starts out in a string in the form of "(515) 555-5555". I'm looking to tokenize the area code, the first 3 digits, and the last 4 digits. The area code I would store in one array, and the other 7 digits in another one. Both arrays are to hold just the numbers themselves.
My code seems to work... sort of. The issue is when I print the two storage arrays, I find some quirks;
My array aCode; it stores the first 3 digits as I ask it to, but then it also prints some garbage values notched at the end. I walked through it in the debugger, and the array only stores what I'm asking it to store- the 515. So how come it's printing those garbage values? What gives?
My array aNum; I can append the tokens I need to the end of it, the only problem is I end up with an extra space at the front (which makes sense; I'm adding on to an empty array, ie adding on to empty space). I modify the code to only hold 7 variables just to mess around, I step into the debugger, and it tells me that the array holds and empty space and 6 of the digits I need- there's no room for the last one. Yet when I print it, the space AND all 7 digits are printed. How does that happen?
And how could I set up my strtok function so that it first copies the 3 digits before the "-", then appends to that the last 4 I need? All examples of tokenization I've seen utilize a while loop, which would mean I'd have to choose either strcat or strcpy to complete my task. I can set up an "if" statement to check for the size of the current token each time, but that seems too crude to me and I feel like there's a simpler method to this. Thanks all!
int main() {
char phoneNum[]= "(515) 555-5555";
char aCode[3];
char aNum[7];
char *numPtr;
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
printf("%s\n", aCode);
numPtr = strtok(&phoneNum[6], "-");
while (numPtr != NULL) {
strcat(aNum, numPtr);
numPtr = strtok(NULL, "-");
}
printf("%s", aNum);
}
I can primarily see two errors,
Being an array of 3 chars, aCode is not null-terminated here. Using it as an argument to %s format specifier in printf() invokes undefined behaviour. Same thing in a differrent way for aNum, too.
strcat() expects a null-terminated array for both the arguments. aNum is not null-terminated, when used for the first time, will result in UB, too. Always initialize your local variables.
Also, see other answers for a complete bug-free code.
The biggest problem in your code is undefined behavior: since you are reading a three-character constant into a three-character array, you have left no space for null terminator.
Since you are tokenizing a value in a very specific format of fixed length, you could get away with a very concise implementation that employs sscanf:
char *phoneNum = "(515) 555-5555";
char aCode[3+1];
char aNum[7+1];
sscanf(phoneNum, "(%3[0-9]) %3[0-9]-%4[0-9]", aCode, aNum, &aNum[3]);
printf("%s %s", aCode, aNum);
This solution passes the format (###) ###-#### directly to sscanf, and tells the function where each value needs to be placed. The only "trick" used above is passing &aNum[3] for the last argument, instructing sscanf to place data for the third segment into the same storage as the second segment, but starting at position 3.
Demo.
Your code has multiple issues
You allocate the wrong size for aCode, you should add 1 for the nul terminator byte and initialize the whole array to '\0' to ensure end of lines.
char aCode[4] = {'\0'};
You don't check if strtok() returns NULL.
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
Point 1, applies to aNum in strcat(aNum, numPtr) which will also fail because aNum is not yet initialized at the first call.
Subsequent calls to strtok() must have NULL as the first parameter, hence
numPtr = strtok(&phoneNum[6], "-");
is wrong, it should be
numPtr = strtok(NULL, "-");
Other answers have already mentioned the major issue, which is insufficient space in aCode and aNum for the terminating NUL character. The sscanf answer is also the cleanest for solving the problem, but given the restriction of using strtok, here's one possible solution to consider:
char phone_number[]= "(515) 555-1234";
char area[3+1] = "";
char digits[7+1] = "";
const char *separators = " (-)";
char *p = strtok(phone_number, separators);
if (p) {
int len = 0;
(void) snprintf(area, sizeof(area), "%s", p);
while (len < sizeof(digits) && (p = strtok(NULL, separators))) {
len += snprintf(digits + len, sizeof(digits) - len, "%s", p);
}
}
(void) printf("(%s) %s\n", area, digits);
I have a tiny problem with my assignment. The whole program is about tree data structures but I do not have problems with that.
My problem is about some basic stuff: reading strings from user input and then storing them in an array list.
char str[1000];
fgets(str, 1000, stdin);
int x = 0;
int y = 0;
int z = 0;
char **list;
list = (char**)malloc((x+1)*sizeof(char));
list[x] = (char*)malloc((y+1)*sizeof(char));
while(str[z] != '\n')
{
list[x][y] = str[z];
z++;
if(str[z] == ',')
{
x++;
y = 0;
list = (char**)realloc(list, (x+1) * sizeof(char*));
list[x] = (char*)malloc((y + 1)*sizeof(char));
z++;
if(str[z] == ' ') // Skips space after the comma
{
z++;
}
}
else if(str[z] == '\n')
{
break;
}
else
{
y++;
list[x] = (char*)realloc(list[x], (y+1)*sizeof(char));
}
}
I pass this list array into another function.
As an example, inputs could be something like
Abcde, Fghijk, Lmnop, Qrstu
and I am trying to split each of these words into the array list.
Abcde
Fghijk
Lmnop
Qrstu
When I try to output the strings I sometimes get weird, excessive characters such as upside down question marks and numbers.
printf("%s ", list[some_number]);
gets me
Fghijk¿
or
Fghijk\200
All of my program works as expected except for this minor problem which I am having trouble solving. Even with the same exact inputs the bugs may or may not appear. I am guessing it has to do with memory allocation?
Thanks for your help!
You need to put '\0' at the end of your new string.
See most of the C library functions such as printf and strlen process strings assuming \0 as the end character of all. Otherwise, they keep on reading the memory out of bounds either making a memory violation or gets some where the value 0 and stops and all the bytes in between in the memory are interpreted to their extended ascii equivalent hence you are getting such a strange behaviour.
So, allocate an extra byte for \0 character and assign it to the last byte.
Either initialize your variables to null, or as tomato said, put a null character at the end of the new string.
C lacks many of the luxuries programmers now take for granted when it comes to memory management. You're on the right path with malloc but that function only allocates memory... it doesn't clear it out. As a result, your variables will have the correct amount of space (critical for reducing memory leaks and overflow errors), but will be filled with garbage. This garbage could be anything, and in your case, it's an upside down question mark. Appropriate, don't you think?
I could be mistaken since I can't run the code myself without more information, but after your
char **list;
list = (char**)malloc((x+1)*sizeof(char));
list[x] = (char*)malloc((y+1)*sizeof(char));
statements, you'll want to do something like this:
list = NULL;
and the like to clear out the garbage.
Furthermore, you may care to use the strlen() function (contained in string.h) to figure out just how many blocks of memory you need to allocate.
Clearing out the spaces you use for variables is a good practice to get into with C. Good to see you learning it as well.