how to insert text input with white space in c? [duplicate] - c

what was the syntax to input strings with more than one word i.e with space in between through scanf() not gets()

Is it
scanf("%[^\t\n]",string);

char name[50];
printf("Enter your full name: ");
scanf("%[^\n]",name);
The %[^\n] conversion asks scanf( ) to keep receiving characters into name[ ] until a \n is encountered. It's a character-set, and starting with ^ means accept anything but that.
See https://en.cppreference.com/w/c/io/fscanf for details on how scanf works.

Better to used fgets() than scanf() for reading a line of user input.
If code must use scanf() then
char buf[100];
// Read up to 99 char and then 1 \n
int count = scanf("%99[^\n]%*1[\n]", buf);
if (count == EOF) {
Handle_EndOfFile(); // or IO error
}
if (count == 0) { // Input began with \n, so read and toss it
scanf("%*c");
}
Now parse buf for individual words.

char field1[40];
char field2[40];
char field3[40];
char field4[40];
char field5[40];
char field6[40];
/*
* sscanf( workarea, format, field of pointers )
* Interpret [^ ] as a field ending in a blank
* Interpret [^' '] as a field ending in a blank
* Interpret [^ |\t] as a field ending in blank or tab char
* Interpret [^' '|\t] as a field ending in blank or tab char
* Interpret [^ |\t\n] as a field ending in blank, tabchar or end-of-line
*
*/
strcpy(workarea,"Bread milk eggs cheese tomatoes cookies \n");
i=sscanf(workarea," %[^' '|\t] %[^[' '|\t] %[^' '|\t] %[^' '|\t] %[^' '|\t] %[^' '|\t|\n] ",
field1,field2,field3,field4,field5,field6);
This scan results in
field1 containing "Bread", field2 containing "milk",... field6 containing "cookies". Between the first to last words you may one or more blanks or tabs
The ending following cookies may be one of the three of space, tab or newline which will be dropped and not be part of "cookies".

I don't think this is possible with scanf().
If you know the number of words you want to read, you can read it with
char str1[100], str2[100];
scanf("%s %s", str1, str2);
Note that this is a huge security loophole, since a user can easily enter a string that's longer than the allocated space.
If you don't know the number of words, you might have to rephrase your question. What do you need to read it for? Why don't you want to use gets(), why does it have to be scanf()?

You could read an entire line from a file if you want with:
scanf("%[^\n]\n", line);
Now, you could use sscanf to get every word:
sscanf(line, "%s", word);
line += strlen(word) + 1;
"line" and "word" are char pointers.
Note how line is going towards to get to the next word.

Related

C Programming. How to pass string in struct array [duplicate]

what was the syntax to input strings with more than one word i.e with space in between through scanf() not gets()
Is it
scanf("%[^\t\n]",string);
char name[50];
printf("Enter your full name: ");
scanf("%[^\n]",name);
The %[^\n] conversion asks scanf( ) to keep receiving characters into name[ ] until a \n is encountered. It's a character-set, and starting with ^ means accept anything but that.
See https://en.cppreference.com/w/c/io/fscanf for details on how scanf works.
Better to used fgets() than scanf() for reading a line of user input.
If code must use scanf() then
char buf[100];
// Read up to 99 char and then 1 \n
int count = scanf("%99[^\n]%*1[\n]", buf);
if (count == EOF) {
Handle_EndOfFile(); // or IO error
}
if (count == 0) { // Input began with \n, so read and toss it
scanf("%*c");
}
Now parse buf for individual words.
char field1[40];
char field2[40];
char field3[40];
char field4[40];
char field5[40];
char field6[40];
/*
* sscanf( workarea, format, field of pointers )
* Interpret [^ ] as a field ending in a blank
* Interpret [^' '] as a field ending in a blank
* Interpret [^ |\t] as a field ending in blank or tab char
* Interpret [^' '|\t] as a field ending in blank or tab char
* Interpret [^ |\t\n] as a field ending in blank, tabchar or end-of-line
*
*/
strcpy(workarea,"Bread milk eggs cheese tomatoes cookies \n");
i=sscanf(workarea," %[^' '|\t] %[^[' '|\t] %[^' '|\t] %[^' '|\t] %[^' '|\t] %[^' '|\t|\n] ",
field1,field2,field3,field4,field5,field6);
This scan results in
field1 containing "Bread", field2 containing "milk",... field6 containing "cookies". Between the first to last words you may one or more blanks or tabs
The ending following cookies may be one of the three of space, tab or newline which will be dropped and not be part of "cookies".
I don't think this is possible with scanf().
If you know the number of words you want to read, you can read it with
char str1[100], str2[100];
scanf("%s %s", str1, str2);
Note that this is a huge security loophole, since a user can easily enter a string that's longer than the allocated space.
If you don't know the number of words, you might have to rephrase your question. What do you need to read it for? Why don't you want to use gets(), why does it have to be scanf()?
You could read an entire line from a file if you want with:
scanf("%[^\n]\n", line);
Now, you could use sscanf to get every word:
sscanf(line, "%s", word);
line += strlen(word) + 1;
"line" and "word" are char pointers.
Note how line is going towards to get to the next word.

C string compare wont allow space bar

using the cprogrammingsimplified tutorial for writing my own stringcompare.
Finished reformatting it and ran it.
works fine for single words,
But
typing space bar skips the second scan and immediately outputs
'words aren't the same'
anyone any idea how to allow the use of even a single space bar?
Thanks in advance.
#include <stdio.h>
int mystrcmp(char s1[], char s2[]);
int main(){
char s1[10], s2[10];
int flag;
printf("Type a string of 10\n\n");
scanf("%s",&s1);
printf("type another string of 10 to compare\n\n");
scanf("%s",&s2);
flag = mystrcmp(s1,s2);
if(flag==0)
printf("the words are the same\n\n");
else
printf("the words are not the same\n\n");
return 0;
}
int mystrcmp(char s1[], char s2[]){
int l=0;
while (s1[l] == s2[l]) {
if (s1[l] == '\0' || s2[l] == '\0')
break;
l++;
}
if (s1[l] == '\0' && s2[l] == '\0')
return 0;
else
return -1;
}
Use fgets() to read full lines, rather than scanf() to read space-separated words.
Remember that fgets() will include the linefeed in the string, though.
It is not strcmp that wouldn't allow space bar, it's scanf with %s format specifier. The input is truncated at the space, so the second string that you read is actually the continuation of the first string.
You can fix this by using %9[^\n] instead of %s in your format specifier:
printf("Type a string of 10\n\n");
scanf("%9[^\n]",s1); //s1 is char [10]
printf("type another string of 10 to compare\n\n");
scanf("%9[^\n]",s2); //s2 is char [10]
9 limits input to nine characters, because you are using a ten-character buffer.
Many answers have told you that scanf("%s",s1) only reads word by word. This is because by default scanf("%s",s1) is delimited by all white spaces, this includes \t, \n, <space>, or any other you can think of.
What scanf("%[^\n]s",s1) does is set the delimiter to \n. So in effect reads all other spaces.
#dasablinklight has also specified a 9 before the '[^\n]' this denotes that scanf() takes 9 values from input buffer.
IMO scanf() is a really nice function due to it's hidden features. I suggest you read more about it in it's documentation.
The problem is that if you type abc def on the first line, the first scanf("%s", s1) (no ampersand required — it should be absent) reads abc and the second reads def. And those are not equal. Type very very and you'd find the words are equal. %s stops reading at a space.
Your buffers of size 10 are too small for comfort.
Fix: read lines (e.g. char s1[1024], s2[1024];) with fgets() or POSIX's getline(), remove trailing newlines (probably: s1[strcspn(s1, "\n")] = '\0'; is a reliable way to do it) and then go ahead compare the lines.

scanf three times in c doesn`t work?

Hello I have a homework from school to make a program that finds a word and replaces it with another in a text. I havent done char string until now and I have a little problem. I need to scan the Text, the find word and the replace word, but only the text scanf work and the other are just skipping..
char w[10000];
char find[10000];
char replace[10000];
int l,c,b,diff,i,k,yes=0,vm;
printf("Text: ");scanf("%[^\n]s",w);
printf("\nFind: ");scanf("%[^\n]s", find);
printf("\nReplace: ");scanf("%[^\n]s", replace);
If you can say why the scanf for find and replace just skips I will be very thankful.
Sorry for bad English not my native language.
Try this
printf("Text: ");scanf("%[^\n]%*c",w);
printf("\nFind: ");scanf("%[^\n]%*c", find);
printf("\nReplace: ");scanf("%[^\n]%*c", replace);
Just consume the newline character and get rid of s after [^\n] which says
Read till newline character is encountered
I would suggest you to use
fgets(w,sizeof(w),stdin);
which is much safer.
scanf("%[^\n]s",w); has multiple problems:
There is no need for s. "%[^\n]" is a complete format specifier. #unwind
There is no input limit. Could use to cope with limits: char w[10000]; scanf("%9999[^\n]", w);
The format does not consume anything is user enters Enter. w remains uninitialized and '\n' remains in stdin for the next scanf() which does the same thing.
// NOT recommended
scanf("%[^\n]%*c", w); This gets stuck on \n only input
Nothing in scanf("%[^\n]",w); consumes the typical trailing '\n'. Code could use the following which also checks the scanf() result.
if (scanf("%9999[^\n]", w) != 1) Handle_EOForEOLonlyInput();
fgetc(stdin);
Suggest instead fgets()
char w[10000];
if (fgets(w, sizeof w, stdin) == NULL) Handle_EOForIOError();
// strip possible ending EOL if needed.
w[strcspn(w, "\n")] = 0;
This should work, since scanf should skip leading whitespace, including newlines.
char w[10000];
char find[10000];
char replace[10000];
/* ... */
printf("Text: ");scanf("%s",w);
printf("\nFind: ");scanf("%s", find);
printf("\nReplace: ");scanf("%s", replace);

storing and printing out elements of structs in C

I have created a simple struct:
struct album {
char title[20];
char artist[20];
};
and later in the program I created an instance a (struct album a;). I only need to ask the user to enter the title and the artist so that I save them in the appropriate place and then print the values:
printf("Please enter your album: \n");
printf("album name: ");
scanf("%.20s", a.title);
fflush(stdin);
printf("artist: ");
scanf("%.20s", a.artist);
printf("======\n");
printf("The album's name is %s and the artist is %s\n", a.title, a.artist);
however when I run this, I get this result:
Part of the input text is lost. What exactly goes wrong here?
scanf reads characters up to white space. So if you are entering Michel Jackson the space in between Michel and Jackson terminates your string so you only get the string Michel.
Try using something like fgets:
fgets(a.artist, 20, stdin);
fgets gets terminates the string on new line rather than white space.
**if you do use fgets make sure to remove the new line character from the end of the string of you do not want a new line character at the end.
With the %s specifier in scanf, the length specifier is the number of characters to write. This differs from most functions which expect the size of the entire buffer.
Since your buffer needs to contain the null terminator, you need to be using "%.19s" here. Another option is to not hardcode the value:
scanf("%.*s", (int)sizeof a.title - 1, a.title);
Note that this only works if a.title is an array (not a pointer), and the cast is necessary because int may be a smaller type than size_t but the * expects int.
As noted by others, %s is for reading up until the next whitespace. You can read up until the next line with %[ , for example:
scanf("%.19[^\n]", a.title);
The ^ means to keep reading until any of the following characters are hit, and \n actually means the newline specifically, not general whitespace.
You will want to flush the buffer after doing this, because the newline will still be in the buffer. However fflush(stdin); is not portable. The portable way to discard the rest of the current line is:
int ch; while( (ch = getchar()) != EOF && ch != '\n' ) { }

Error in storing char as variable from user input

the idea is that i type in a sentence and store it as a string... then i can choose a letter and change it to a different letter
int main(int argc, char *argv[])
{
char string[100];
char newLetter;
char oldLetter;
int i = 0;
printf("Please enter your sentence : ");
gets(string);
printf("\n\nWord is : %s" , string );
printf("\n\nTarget : ");
scanf("%s", &oldLetter);
printf("Replace with : ");
scanf("%s", &newLetter);
for ( i = 0; i < sizeof(string); i++)
{
if (string[i] == oldLetter)
{
string[i] = newLetter;
break;
}
}
printf("\n\nWord is : %s" , string );
system("PAUSE");
return 0;
}
any help in where I've gone wrong is appreciated
eg.
input could be - yellow lorry red lorry
then target - r
change to - t
output - yellow lotty ted lotty
Change the %s in the scanning of the two letters to %c and the code will run flawlessly.
First things first, since you are aiming to store a character to char oldLetter and char newLetter via scanf, you should be using the format specifier %c instead of the %s.
However, that won't be enough, because of the following: When you use functions like scanf or gets, you prompt user to input characters to the stdin stream. stdin stream is a buffered stream. You may think of it as a:
Stream of river that you;
drop characters into
each character you drop remains inside the river
until something takes them out
When scanf comes, and you type, say, A and then press the enter key, you put the following characters in the stream:
'A' '\n'
Where \n is the new-line character. With the enter key-press, you also inform the scanf that you're done. scanf then starts issuing the stdin buffer, let's see... 'A', a proper value for %c character. It takes that one out, leaves \n behind.
Then the next scanf comes, seeks for a %c in stream, finds the \n ready, takes that out. This is what you wouldn't want. Two ways to prevent it:
use fflush( stdin ); after the scanf calls, or
use while( getchar( ) != '\n' ); after the scanf calls
to dismiss/discard the remaining characters in the buffer.
And get rid of that break; if you want to replace each occurrence and not just the first one.
You can do it right, or you can do it wrong and hope that the person doesn't enter the right series of keystrokes or pipe in a file that doesn't end in newline, to break it ... up to you

Resources