why I can't get multiple spaces in *? - c

int main()
{
int input;
printf("input lenth : \n");
scanf("%d", &input);
while(getchar()!='\n')
continue;
printf("input str : \n");
char* sentence = (char*)malloc(sizeof(char) * input);
fgets(sentence, sizeof(sentence), stdin);
reverse(sentence, strlen(sentence));
free(sentence);
return 0;
}
I learn fgets can get space.
so I malloc enough space to sentence ex) 100
and I input I am a boy
But when I print my sentence, IT just print I am a ...
what's th problem?

This statement
fgets(sentence, sizeof(sentence), stdin);
is incorrect. It seems you mean
fgets(sentence, input, stdin);
Otherwise sizeof( sentence ) will yield the size of a pointer declared like
char* sentence = (char*)malloc(sizeof(char) * input);
Pay attention to that the function fgets can append the new line character '\n' to the entered string. You should remove it like
sentence[ strcspn( sentence, "\n" ) ] = '\0';

When you say:
fgets(sentence, sizeof(sentence), stdin);
It gives you size of pointer char i.e. 8 (Depends on 32 & 64 system you use).
So you are able to receive 7 characters only as fgets assignes '\0' character to last character.
So, use length you received from the user i.e. 100.
fgets(sentence, input, stdin);

Related

Input of multiple char arrays isn't working [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 1 year ago.
char toFind[100];
char replace[100];
int pos = 0;
printf("Enter a text: ");
scanf("%[^\n]", str);
printf("Enter a search pattern: ");
scanf("%[^\n]", toFind);
printf("Enter a substitute: ");
scanf("%[^\n]", replace);
pos = strnfnd(0, toFind);
strins(pos, replace);
printf("Der Text ist: %s", str);
This code sample let me read the value for str but skips the other two scanf. I have no idea why.
What can I do to fix this?
Ps: str is a global char array
After this call of scanf
scanf("%[^\n]", str);
the new line character '\n' still is present in the input buffer.
So the next call of scanf
scanf("%[^\n]", toFind);
that reads input until the new line character '\n' is encountered reads nothing.
You should write for example
scanf("%[^\n]%*c", str);
to remove the new line character '\n' from the input buffer.
Here is a demonstration program
#include <stdio.h>
int main( void )
{
char s[100];
scanf( "%99[^\n]%*c", s );
puts( s );
scanf( "%99[^\n]", s );
puts( s );
return 0;
}
In this case if to enter strings for example like
Hello
World
then the output will be
Hello
World
Another and more simple approach is to prepend the format string with a blank. For example
scanf(" %[^\n]", toFind);
^^^^
In this case all leading white space characters will be skipped.
Here is a demonstration program.
#include <stdio.h>
int main( void )
{
char s[100];
scanf( "%99[^\n]", s );
puts( s );
scanf( " %99[^\n]", s );
puts( s );
return 0;
}
In this case if to enter strings as shown above that is
Hello
World
then the program output will be
Hello
World
It depends where you run the compiled code - the operating system. In some cases when the "Enter" key is pressed, two bytes are emitted in the input stream (10 and 13) instead of '\n' (10). In that case you need to flush the extra symbols. Check the comments for the exact implementation.
There are problems with your scanf() usage: scanf("%[^\n]", str);
you do not specify the maximum number of characters to store into str, hence a sufficiently long line typed by the user will cause undefined behavior. This is a typical software flaw hackers can try and exploit. You can prevent this by specifying the limit as scanf("%99[^\n]", str);
you do not read the trailing newline entered by the user, so the next call scanf("%[^\n]", toFind); will fail because no characters different from '\n' are present in the input stream, since the first pending byte is '\n', or EOF.
you do not check the return value of the scanf() calls, so you cannot detect input errors such as the above.
note however that scanf("%99[^\n]", str); will fail if the user types enter immediately and str will not be modified in this case.
It is much safer to use fgets() instead of scanf() for this task:
char str[100];
char toFind[100];
char replace[100];
int pos = 0;
printf("Enter a text: ");
if (!fgets(str, sizeof str, stdin)) {
printf("input error\n");
return 1;
}
str[strcspn(str, "\n")] = '\0'; /* strip the trailing newline if any */
printf("Enter a search pattern: ");
if (!fgets(toFind, sizeof toFind, stdin)) {
printf("input error\n");
return 1;
}
toFind[strcspn(toFind, "\n")] = '\0'; /* strip the trailing newline if any */
printf("Enter a substitute: ");
if (!fgets(replace, sizeof replace, stdin)) {
printf("input error\n");
return 1;
}
replace[strcspn(replace, "\n")] = '\0'; /* strip the trailing newline if any */
pos = strnfnd(0, toFind);
strins(pos, replace);
printf("Der Text ist: %s\n", str);

Function fgets skips user input?

When I use the function fgets, the program skips the user input, effecting the rest of the program. An example program with this effect is:
#include <stdio.h>
int main() {
char firstDigit[2];
char secondDigit[2];
printf("Enter your first digit: ");
fgets(firstDigit, 1, stdin);
printf("\nEnter your second digit: ");
fgets(secondDigit, 1, stdin);
printf("\n\nYour first digit is %s and your second digit is %s.\n", firstDigit, secondDigit);
}
I then thought that maybe the problem was that fgets might be writing the newline, so I changed the code to account for that:
#include <stdio.h>
int main() {
char firstDigit[3];
char secondDigit[3];
printf("Enter your first digit: ");
fgets(firstDigit, 2, stdin);
printf("\nEnter your second digit: ");
fgets(secondDigit, 2, stdin);
printf("\n\nYour first digit is %c and your second digit is %c.\n", firstDigit[0], secondDigit[0]);
}
This time, the first input works properly, but the second input is skipped.
What am I doing incorrectly?
char firstDigit[2] and char secondDigit[2] are not large enough to hold a digit, a newline character, and a null-terminator:
char firstDigit[3];
char secondDigit[3];
Then, the calls to fgets() need to specify the size of the buffer arrays:
fgets(firstDigit, sizeof firstDigit, stdin);
/* ... */
fgets(secondDigit, sizeof secondDigit, stdin);
When instead fgets(firstDigit, 2, stdin); is used, fgets() stores at most two characters, including the \0 character, in firstDigit[]. This means that the \n character is still in the input stream, and this interferes with the second call to fgets().
In answer to OP's comment, How would you remove the unread characters from the input stream?, a good start would be to use more generous allocations for firstDigit[] and secondDigit[]. For example, char firstDigit[100], or even char firstDigit[1000] will be large enough that any expected input will be taken in by fgets(), leaving no characters behind in the input stream. To be more certain that the input stream is empty, a portable solution is to use the idiomatic loop:
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
Note here that it is necessary to check for EOF, since getchar() may return this value if the user signals end-of-file from the keyboard, or if stdin has been redirected, or in the unlikely event of an input error. But also note that this loop should only be used if there is at least a \n character still in the input stream. Before attempting to clear the input stream with this method, the input buffer should be checked for a newline; if it is present in the buffer, the input stream is empty and the loop should not be executed. In the code below, strchr() is used to check for the newline character. This function returns a null pointer if the sought-for character is not found in the input string.
#include <stdio.h>
#include <string.h> // for strchr()
int main(void)
{
char firstDigit[3]; // more generous allocations would also be good
char secondDigit[3]; // e.g., char firstDigit[1000];
printf("Enter your first digit: ");
fgets(firstDigit, sizeof firstDigit, stdin);
/* Clear input stream if not empty */
if (strchr(firstDigit, '\n') == NULL) {
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
putchar('\n');
printf("Enter your second digit: ");
fgets(secondDigit, sizeof secondDigit, stdin);
/* Clear input stream if not empty */
if (strchr(secondDigit, '\n') == NULL) {
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
puts("\n");
printf("Your first digit is %c and your second digit is %c.\n",
firstDigit[0], secondDigit[0]);
return 0;
}
It may be even better to use a single buffer[] to store lines of input, and then to store individual characters in chars. You could also write a function to clear the input stream, instead of rewriting the same loop each time it is needed:
#include <stdio.h>
#include <string.h> // for strchr()
void clear_stdin(void);
int main(void)
{
char buffer[1000];
char firstDigit;
char secondDigit;
printf("Enter your first digit: ");
fgets(buffer, sizeof buffer, stdin);
firstDigit = buffer[0];
/* Clear input stream if not empty */
if (strchr(buffer, '\n') == NULL) {
clear_stdin();
}
putchar('\n');
printf("Enter your second digit: ");
fgets(buffer, sizeof buffer, stdin);
secondDigit = buffer[0];
/* Clear input stream if not empty */
if (strchr(buffer, '\n') == NULL) {
clear_stdin();
}
puts("\n");
printf("Your first digit is %c and your second digit is %c.\n",
firstDigit, secondDigit);
return 0;
}
void clear_stdin(void)
{
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
For the first case, fgets(firstDigit, 1, stdin); cannot read anything from the input because the buffer has a size of only 1 byte, and fgets() must store a null terminator into the destination.
For the second case: fgets(firstDigit, 2, stdin); reads 1 byte from stdin, the digit that you typed, and cannot read the newline because the destination array is already full, allowing for the null terminator. The second fgets() reads the pending newline from the first entry and returns immediately for the same reason, not letting you type the second input.
You must allow fgets() to read at least 2 bytes by providing a buffer size of at least 3:
#include <stdio.h>
int main(void) {
char firstDigit[3];
char secondDigit[3];
printf("Enter your first digit: ");
if (!fgets(firstDigit, sizeof firstDigit, stdin))
return 1;
printf("\nEnter your second digit: ");
if (!fgets(secondDigit, sizeof secondDigit, stdin))
return 1;
printf("\n\nYour first digit is %s and your second digit is %s.\n",
firstDigit, secondDigit);
return 0;
}
Note that if you type more than a single character before the enter key, the program will still behave in an unexpected way.
This is a buffer problem. When you press enter, don't know why it is saved in the stdin buffer.
After you perform an fgets(...) you must type fflush(stdin); on all circumstances.
Something like this:
printf("Enter your first digit: ");
fgets(firstDigit, 1, stdin);
fflush(stdin);

Why is strtok printing only first word?

I am using strtok for converting string into individual words. I have done the following:
int main() {
char target[100];
char *t;
scanf("%s",target);
t = strtok(target," ");
while (t!= NULL)
{
printf("<<%s>>\n", t);
t = strtok (NULL, " ");
}
return 0;
}
The input is a string such as 'this is a string', the output I am getting is<<this>>.
The way you have written scanf it will accept string till white space only
scanf("%s",target);
SO You need to change the way you take input from console
scanf("%99[^\n]",target);
Change:
scanf("%s",target);
to:
fgets(target, 100, stdin);
since the first won't stop when encounters the whitespace in your input.
Output:
this is a string
<<this>>
<<is>>
<<a>>
<<string
>>
Notice how the newline fgets() stores affects the output. You can simply discard it if you want, like this:
fgets(target, 100, stdin);
target[strlen(target) - 1] = '\0';
and now the output is:
this is a string
<<this>>
<<is>>
<<a>>
<<string>>
If you want to continue using scanf(), then you can use the below code snippet:
#include<stdio.h>
#include <string.h>
int main() {
char target[100];
char *t;
//scanf("%s",target);
scanf("%99[0-9a-zA-Z ]", target);
printf("%s\n",target);
t = strtok(target," ");
while (t!= NULL)
{
printf("<<%s>>\n", t);
t = strtok (NULL, " ");
}
return 0;
}
Working code here.
Just writing scanf("%s",target); will read the input only till the first white space; which is why you get only the first word as the output. By writing scanf("%99[0-9a-zA-Z ]", target);, you are reading 99 characters (including numbers 0-9, a-z or A-Z and white space) from the input stream.
Hope this is helpful.

Read a string as an input using scanf

I am new to C language and I am trying read a character and a string (a sentence; max-length 25) from a user.
Not sure what I am doing wrong in the following lines of code, its giving me an error "Segment Fault".
#include <stdio.h>
int main(){
char * str[25];
char car;
printf("Enter a character: ");
car = getchar();
printf("Enter a sentence: ");
scanf("%[^\n]s", &str);
printf("\nThe sentence is %s, and the character is %s\n", str, car);
return 0;
}
Thanks!
You have to make four changes:
Change
char * str[25];
to
char str[25];
as you want an array of 25 chars, not an array of 25 pointers to char.
Change
char car;
to
int car;
as getchar() returns an int, not a char.
Change
scanf("%[^\n]s", &str);
to
scanf( "%24[^\n]", str);
which tells scanf to
Ignore all whitespace characters, if any.
Scan a maximum of 24 characters (+1 for the Nul-terminator '\0') or until a \n and store it in str.
Change
printf("\nThe sentence is %s, and the character is %s\n", str, car);
to
printf("\nThe sentence is %s, and the character is %c\n", str, car);
as the correct format specifier for a char is %c, not %s.
str is an array of 25 pointers to char, not an array of char. So change its declaration to
char str[25];
And you cannot use scanf to read sentences--it stops reading at the first whitespace, so use fgets to read the sentence instead.
And in your last printf, you need the %c specifier to print characters, not %s.
You also need to flush the standard input, because there is a '\n' remaining in stdin, so you need to throw those characters out.
The revised program is now
#include <stdio.h>
void flush();
int main()
{
char str[25], car;
printf("Enter a character\n");
car = getchar();
flush();
printf("Enter a sentence\n");
fgets(str, 25, stdin);
printf("\nThe sentence is %s, and the character is %c\n", str, car);
return 0;
}
void flush()
{
int c;
while ((c = getchar()) != '\n' && c != EOF)
;
}
// This is minimal change to your code to work
#include <stdio.h>
int main(){
char car,str[25];
printf("Enter a character: ");
car = getchar();
printf("Enter a sentence: ");
scanf("%s", str);
printf("\nThe sentence is %s, and the character is %c\n", str, car);
return 0;
}

Tokenizing a string

I am in the process of writing a C program that parses a string and tokenizing it by breaking the string characters into words that are seperated by white space. My question is when i run my current program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char input[20];
printf("Please enter your word:\n");
scanf("%c", &input);
printf("%c", input[1]);
return 0;
}
If i was to enter the word "This", i would expect to get back "h" when i run the program but instead i get a downwards pointing arrow. However, when the input is set to print out input[0] i get back a "T".
Edit: I have modified my code so that it prints out the whole string now which i will show below
int main()
{
char input[20];
printf("Please enter your words:\n");
scanf("%s", input);
printf("%s", input);
return 0;
}
My goal is to be able to break that string into chars that i can search through to find whitespace and thus being able to isolate those words for example, if my input was "This is bad" i'd like the code to print out
This
is
bad
Edit:
I have modified my code to fit one of these answers but the problem i run into now is that it won't compile
int main()
{
char input[20];
printf("Please enter your words:\n");
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
}
printf("%c", input[]);
return 0;
Problems:
1) scanf("%c", input); only set the first element of the array input.
2) printf("%c", input[1]); prints the second element of the array input, which has uninitialized data in it.
Solution:
Small state machine. No limit on string size like 20.
#include <ctype.h>
#include <stdio.h>
int main() {
int ch = fgetc(stdin);
while (ch != EOF) {
while (isspace(ch)) {
// If only 1 line of input allowed, then add
if (ch == '\n') return 0;;
ch = fgetc(stdin);
}
if (ch != EOF) {
do {
fputc(ch, stdout);
ch = fgetc(stdin);
} while (ch != EOF && !isspace(ch));
fputc('\n', stdout);
}
}
return 0;
}
scanf("%c", &input); does not do what you think it does.
First of all, %c scans only a single character: http://www.cplusplus.com/reference/cstdio/scanf/
Second, array's name is already a pointer to it's first element, so stating &input you make a pointer to a pointer, so instead of storing your character in array's first element you store it in pointer to the array which is a very bad thing.
If you really want to use scanf, I recommend a loop:
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
Using scanf("%s", input") leaves you vulnerable to buffer overflow attacks if the word is longer than 20 characters http://en.wikipedia.org/wiki/Buffer_overflow
In my example I assumed, that you want to finish your word with a newline character.
EDIT: In scanf documentation is also a good example:
scanf("%19s", input);
It scans no more than 19 characters, which also prevent buffer overflow. But if you want to change input size, you have to change it two places.
You can use
char * strtok ( char * str, const char * delimiters );
to tokenize your string. If you have your input in input[] array and want to tokenize the string accoring to whitespace character, you can do the following :
char *ptr;
ptr = strtok(input, " ");
while(ptr != NULL) {
printf("%s\n", ptr);
ptr = strtok(NULL, " ");
}
Only the first call to strtok() requires the character array as input. Specifying NULL in the next calls means that it will operate on the same character array.
Your scanf only picks up the first character, input[1] contains random garbage. Use scanf("%19s", input) instead.

Resources