Why does the second strncpy give incorrect weird symbols when printing?
Do I need something like fflush(stdin) ?
Note that I used scanf("%s",aString); to read an entire string, the input that is entered starts first off with a space so that it works correctly.
void stringMagic(char str[], int index1, int index2)
{
char part1[40],part2[40];
strncpy(part1,&str[0],index1);
part1[sizeof(part1)-1] = '\0';//strncpy doesn't always put '\0' where it should
printf("\n%s\n",part1);
strncpy(part2,&str[index1+1],(index2-index1));
part2[sizeof(part2)-1] = '\0';
printf("\n%s\n",part2);
}
EDIT
The problem seems to lie in
scanf("%s",aString);
because when I use printf("\n%s",aString); and I have entered something like "Enough with the hello world" I only get as output "Enough" because of the '\0'.
How can I correctly input the entire sentence with whitespace stored? Reading characters?
Now I use: fgets (aString, 100, stdin);
(Reading string from input with space character?)
In order to print a char sequence correctly using %s it needs to be null-terminated. In addition the terminating symbol should be immediately after the last symbol to be printed. However this section in your code: part2[sizeof(part2)-1] = '\0'; always sets the 39th cell of part2 to be the 0 character. Note that sizeof(part2) will always return the memory size allocated for part2 which in this case is 40. The value of this function does not depend on the contents of part2.
What you should do instead is to set the (index2-index1) character in part2 to 0. You know you've copied that many characters to part2, so you know what is the expected length of the resulting string.
Related
What happens to the last (nth) character of a n-character string when I try to output the string?
I've included my code, sample input and output below that highlights that the last character I input is lost.
Code:
char buffer[10];
fgets(buffer, sizeof(buffer), stdin);
printf("%s", buffer);
return 0;
Input:
aaaaaaaaab (that's 9 a's followed by 1 b)
Output:
aaaaaaaaa (9 a's)
For an array of characters to be treated as a propper string, its last character must be a null terminator (or null byte) '\0'.
The fgets function, in particular always makes sure that this character is added to the char array, so for a size argument of 10 it stores the first 9 caracters in the array and a null byte in the last available space, if the input is larger than or equal to 9.
Be aware that the unread characters, like b in your sample case, will remain in the input buffer stdin, and can disrupt future input reads.
This null byte acts as a sentinel, and is used by functions like printf to know where the string ends, needless to say that this character is not printable.
If you pass a non null terminated array of characters to printf this will amount to undefined behavior.
Many other functions in the standard library (and others) rely on this to work properly so it's imperative that you make sure that all your strings are properly null terminated.
Char arrays have continuously confused me in C.
Here is the following code:
char tcp_port[100], udp_port[6];
tcp_port[99] = '\0'; udp_port[5] = '\0';
fscanf(fp, " tcp_port=%s", tcp_port);
fscanf(fp, " udp_port=%s", udp_port);
printf("%s\n", tcp_port); printf("%s\n", udp_port);
This works and prints out the right number. However, since tcp_port has 100 elements, how do those just disappear when printing? The port is only 5 characters long and the last element is null terminated. Does printf just ignore those unintialized elements, and do those uninitialized elements contain random data?
Yes, printf() only prints the characters up to the first \0 character. All C string functions do this. They also automatically append that \0 character when necessary, like the scanf() function there. That's why it's called a "0-terminated string".
The other elements can contain anything and they will be completely ignored. In practice, they usually contain random junk, but it depends on a variety of factors.
Note that when you allocate memory you must keep that \0 character in mind. Your tcp_port string can only at most 99 characters, because the last one must be 0.
I have a program where I need to scanf a string, which I know it will be only 2 characters long. (for example: "ex").
what is the proper way to do that?
I was going for:
char myStr[3];
scanf("%s", myStr);
It works just fine, but when I enter a 10-letter word it also works just fine. How come? Does the [3] has no meaning? How should I do this the proper way?
Thanks.
The proper way to limit the input using scanf() is
if (scanf("%2s", myStr) != 1) /* error */;
But consider using fgets() rather than scanf()
if (fgets(myStr, sizeof myStr, stdin) == NULL) /* error */;
It works just fine, but when I enter a 10-letter word it also works
just fine.
It only appears to work fine but it's actually undefined behaviour. That is because scanf stores the characters it reads from stdin into the buffer pointed to by myStr. The size of myStr is 3. Therefore, there's space for only 2 characters. One character space is saved for the terminating null byte to mark the end of the string which is added by scanf automatically. When the input string is longer than 2 characters, scanf overruns the buffer accessing memory out of the bound of the array. It is illegal to access memory out of the array bound and invokes undefined behaviour.
The next time, it may very well crash. It's unpredictable and you should always avoid it.
To guard against it, you should specify maximum field width for the conversion specifier %s in the format string of scanf. It should be one less than the array size to accommodate the terminating null byte.
char myStr[3];
scanf("%2s", myStr);
Better still, I suggest you to use fgets.
char myStr[3];
// read and store at most one less than
// sizeof(myStr) chars
fgets(myStr, sizeof myStr, stdin);
but when I enter a 10-letter word it also works just fine. How come? Does the [3] has no meaning?
I doesn't work fine. See in this example:
#include <stdio.h>
int
main(int argc, char **argv)
{
char second[5] = "BBBB";
char myStr[3] = {0};
scanf("%s", myStr);
printf("second = %s\n", second);
printf("myStr = %s\n", myStr);
return 0;
}
writing only two characters in myStr is fine:
a.exe
AA
second = BBBB
myStr = AA
writing more data overrides the near by memory of second:
a.exe
AAAAAAA
second = AAAA
myStr = AAAAAAA
You need to limit the number of characters scanf reads using something like
scanf("%2s", myStr);, 2 is the size of myStr - 1.
You canĀ“t do that.
scanf will do nothing to prevent it, but it can (or, in larger programs, will)
lead to problems later on. Like unexpectly changed variable values, program crashes...
Use fgets
So I'm writing a small program (I'm new to C, coming from C++), and I want to take in a string of maximum length ten.
I declare a character array as
#define SYMBOL_MAX_LEN 10 //Maximum length a symbol can be from the user (NOT including null character)
.
.
.
char symbol[SYMBOL_MAX_LEN + 1]; //Holds the symbol given by the user (+1 for null character)
So why is it when I use:
scanf("%s", symbol); //Take in a symbol given by the user as a string
I am able to type '01234567890', and the program will still store the entire value?
My questions are:
Does scanf not prevent values from being recorded in the adjacent
blocks of memory after symbol?
How could I prevent the user from entering a value of greater than length SYMBOL_MAX_LEN?
Does scanf put the null terminating character into symbol automatically, or is that something I will need to do manually?
You can limit the number of characters scanf() will read as so:
#include <stdio.h>
int main(void) {
char buffer[4];
scanf("%3s", buffer);
printf("%s\n", buffer);
return 0;
}
Sample output:
paul#local:~/src/c/scratch$ ./scanftest
abc
abc
paul#local:~/src/c/scratch$ ./scanftest
abcdefghijlkmnop
abc
paul#local:~/src/c/scratch$
scanf() will add the terminating '\0' for you.
If you don't want to hardcode the length in your format string, you can just construct it dynamically, e.g.:
#include <stdio.h>
#define SYMBOL_MAX_LEN 4
int main(void) {
char buffer[SYMBOL_MAX_LEN];
char fstring[100];
sprintf(fstring, "%%%ds", SYMBOL_MAX_LEN - 1);
scanf(fstring, buffer);
printf("%s\n", buffer);
return 0;
}
For the avoidance of doubt, scanf() is generally a terrible function for dealing with input. fgets() is much better for this type of thing.
Does scanf not prevent values from being recorded in the adjacent blocks of memory after symbol?
As far as I know, No.
How could I prevent the user from entering a value of greater than length SYMBOL_MAX_LEN?
By using buffer safe functions like fgets.
Does scanf put the null terminating character into symbol automatically, or is that something I will need to do manually?
Only if the size was enough for it to put the nul terminator. For example if your array was of length 10 and you input 10 chars how will it put the nul terminator.
I am able to type '01234567890', and the program will still store the entire value?
This is because you are Unlucky that you are getting your desired result. This will invoke undefined behavior.
Does scanf not prevent values from being recorded in the adjacent blocks of memory after symbol?
No.
How could I prevent the user from entering a value of greater than length SYMBOL_MAX_LEN?
Use fgets.
Does scanf put the null terminating character into symbol automatically, or is that something I will need to do manually?
Yes
I have an archive file that looks like this:
!<arch>
file1.txt/ 1350248044 45503 13036 100660 28 `
hello
this is sample file 1
Now in here, the number 28 in the header is the file1.txt size. To get that number, I use:
int curr_char;
char file_size[10];
int int_file_size;
curr_char = fgetc(arch_file);
while(curr_char != ' '){
strcat(file_size, &curr_char);
curr_char = fgetc(arch_file);
}
// Convert the characters to the corresponding integer value using atoi()
int_file_size = atoi(file_size);
However, values in the file_size array change every time I run my code. Sometimes it's correct, but mostly not. Here are some examples of what I get for file_size:
?28`U
2U8U
28 <--- Correct!
pAi?28
I believe the problem is with my strcat() function, but not sure. Any help would be appreciated.
You shouldn't read the file character wise. There are higher level functions doing this. As larsmans already pointed out, you can use fscanf() for this task:
fscanf(arch_file, "%d", &int_file_size);
&curr_char is an int*, so you're copying over the bits of an int as if they represented a string.
You should be using scanf.
The expression &curr_char points to a single character (well, actually an integer as that's how you declared it). strcat looks for a string, and string as you should know are terminated by a '\0' character. So what strcat does in your case is use the &curr_char pointer as the address of a string and looks for the terminator. Since that is not found weird stuff will happen.
One way of solving this is to make curr_char an array, initialized to zero (the string terminator character) and read into the first entry:
char curr_char[2] = { '\0' }; /* Will make all character in array be zero */
...
curr_char[0] = fgetc(...);
There is also another problem, and that is that you are trying to concatenate into a string that is not initialized. When running your program, the array file_size can contain any data, it's not automatically zeroed out. This leads to the weird characters before the number. This is solved partially the same way as the above problem, by initializing the array:
char file_size[10] = { '\0' };