scanf() is not working for getting a sentence - c

I am learning the language C by myself and with the help of internet.
I came across an exercise, and I was able to read in everything with integers and double, but allowing the user to type in a full sentence and store it in a variable has given me hard time. Can someone explain how I can get a sentence from the user, and store it in a variable. I have tried many things, such as [%^\n] with scanf, and also fget but I am having some trouble. For some reason, it is not working.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int i = 4;
double d = 4.0;
char s[] = "Orange ";
// Declare second integer, double, and String variables.
int secondInt;
double justDouble;
char variable[500];
// Read and save an integer, double, and String to your variables.
scanf("%d", &secondInt);
scanf("%lf", &justDouble);
scanf("%[^ \n]", variable);
// Print the sum of both integer variables on a new line.
printf("%i\n ", i + secondInt);
// Print the sum of the double variables on a new line.
printf("%.1lf\n ", d + justDouble);
// Concatenate and print the String variables on a new line
printf("%s ", s);
printf("%s ", variable);
// The 's' variable above should be printed first.
return 0;
}

This should do the trick by using fgets() in general
#include <stdlib.h>
#include <stdio.h>
int main()
{
// variable to store the message
char msg[100];
// prompting the user to enter the message
printf("Pls enter a msg: ");
// using fgets() to retrieve a whole sentence from the user
fgets(msg, 100, stdin);
// printing the message to stdout
printf("%s", msg);
}
You can learn more about fgets here:
https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm
Let me know if anything is not clear so I can improve my answer

To work with scanf, you need to make sure that everything entered gets read.
In your example, you first expect an integer, and then a double. What does the user type to 'finish' entering the integer? Probably a <RET> (or a blank) - and now you need to scanf these too! Or they will 'clog' the input stream.
For example, your second scanf could be scanf(" %lf"... - note the blank before the % sign, it will read (and discard) any number of whitespace (which is <RET>, <TAB>, <space>).
scanf is very powerful, but needs a lot of detail understanding to be used correctly. Most people don't get it, and therefore claim "it's old and bad and shouldn't be used".
In professional software, it is generally avoided; not because it's not capable, but because the chance is too high that is used wrong, or that it is encountered by a developer that changes it and messes it up.

Related

How do i solve this question related to string_Concatenation using C?

I am new to coding. This is a Question from the #30 days code on Hackerrank.
But, I'm unable to solve it. can anyone help me by telling me what's the problem here?
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int i = 4;
double d = 4.0;
char s[] = "Hello ";
// Declare second integer, double, and String variables.
int j;
char *ptr=s;
double c;
char p[100];
// Read and save an integer, double, and String to your variables.
scanf("%d",&j);
scanf("%lf",&c);
scanf("%[^\n]%*c",p);
// Print the sum of both integer variables on a new line.
printf("%d\n",i+j);
printf("%.1lf\n",c+d);
printf("%s%s",s,p);
// Print the sum of the double variables on a new line.
// Concatenate and print the String variables on a new line
// The 's' variable above should be printed first
return 0;
}
It is showing the result
Input:
12
4
Output:
16
8.0
Hello o}┌vl
╤
As you can see I want to print concatenated string but it wouldn't even allow me to input the data into the string.
I guess you press the Enter key for all input?
That Enter key will be added as a newline in the input buffer.
The %[^\n] format stops reading once it find a newline. And the first character it reads is a newline. So it doesn't read anything, and the array p will remain uninitialized with indeterminate contents.
You need to tell scanf to skip the leading newline, which is done by adding an explicit space in the format string:
scanf(" %99[^\n]",p);
// ^
// Note space here
Note that I limit the input to 99 characters, which will not overflow the buffer. And also note that you don't need to read the newline after the string.

Scanf won't notice '\n' char in a program loading only numbers

I have been searching for a few days and I have found only one solution that didn't look perfect to me. Our teacher asked us to create a function that would calculate total lenght of distances in between points provided by user.
My idea was to write code this way, using an array of specific type.
The issue is that, I can't come up with any ideas for how to solve the issue with input: He asked us to make the program end once the user doesn't type anything, so I take it for enter - \n sign.
I could use fgets to get the first variable but:
First, I feel like I don't know any other way beside an array for keeping a long decimal number(in a form of a char array with elements making up the number), that the user could put on the input. I don't know if his script doesn't put some "rofl" number in there.
Second, in this case I think that stripping that array off one X would totally break the total structure of this program. I would rather take both X and Y and accept them as char type, but then the function like atof would probably understand only the X and would stop working after the \n sign.
So Y would be left not given. The accepted input numbers should be of double type. Like:
2 2
3 3
-2 4.5
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
double lenght(struct point *coordinates, int n);
struct point {
double x;
double y;
};
int main()
{
double x,y,TwiceAsBig=3;
int i=0,l=0;
struct point *coordinates;
coordinates = (struct point*)malloc(sizeof(*coordinates)*3);
//allocation of memory for pointtype array with a pointer
while(scanf("%lg %lg",&x,&y)==2)
{
coordinates[i].x=x;
coordinates[i].y=y;
i++;
if(i==TwiceAsBig)
{
coordinates = (struct point*)realloc(coordinates, 2*i*sizeof(*coordinates));
TwiceAsBig=2*TwiceAsBig;
}
}
printf("\n");
for(l;l<i;l++)
{
printf("%lg %lg\n", coordinates[l].x,coordinates[l].y);
}
//checking on the array if the values were loaded correctly
printf("%lg",lenght(coordinates,i));
}
//function for dinstace in between the points
double lenght(struct point*coordinates,int n)
{
int l=0;
for(l;l<n;l++)
{
printf("%lg %lg\n", coordinates[l].x,coordinates[l].y);
}
int pair=0;
double lenght,distance;
for(int AoP;AoP<n-1;AoP++)
{
distance=sqrt(pow(coordinates[pair+1].x-coordinates[pair].x,2)+pow(coordinates[pair+1].y-coordinates[pair].y,2));
pair++;
printf("%lg: ", distance);
lenght=lenght+distance;
}
return lenght;
}
As for your problem, using fgets to read a whole line, and the possibly use sscanf to parse out the two numbers might work.
The problem with using only scanf is that all the numeric format specifiers reads and skips leading white-space automatically, and newline is a white-space character. That means your scanf call in the loop condition will wait until there's some actual non-space characters being input (followed by a newline of course, which leads to the cycle starting over again).
What about using scanf("%[^\n]%*c", test); to read a full string.
Then parsing the result using sscanf?
Something like this:
char* userinput = (char*) malloc(sizeof(char) * 100);
scanf("%[^\n]%*c", userinput);
double a, b;
sscanf(userinput, "%lg %lg", &a, &b);
printf("sum %lg\n", a+b);
With input "-5.5 3.2" the code produces "sum -2.3".
%[^\n]%*c is a "scanset" which tells scanf to read everything excluding '\n' and once it reaches a newline it reads the newline character and disregards it.
You could even use scansets to check the input to some degree by specifying which type of characters you expect to read.
%[0-9 .\\-] // would read digits from 0-9, 'space', '.' and '-'

C Program Array more than 1 word [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
This question is from HackerRank, I try to use %[^\n]s for a long word. But, the output keep on producing .0
How to replace %[^\n]s to something else for the string to receive the input ?
Here is the input :
12
4.0
is the best place to learn and practice coding!
Here is my output :
16
8.0
HackerRank .0
This is the expected output :
16
8.0
HackerRank is the best place to learn and practice coding!
This is my full code, as you can see, it does not recognize %[^\n]s. How to solve this problem? Thank you.
Full code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main() {
int i = 4;
double d = 4.0;
char s[] = "HackerRank ";
// Declare second niteger, double, and String variables.
int value1, sum1, value2;
double e = 2.0, sum2;
char t[30];
// Read and save an integer, double, and String to your variables.
scanf(" %d", &value1);
scanf("%d", &value2);
scanf("%[^\n]s", t); //** POINT OF INTEREST **
// Print the sum of both integer variables on a new line.
sum1 = value1 + i;
printf("%d\n", sum1);
// Print the sum of the double variables on a new line.
sum2 = d * e;
printf("%.1lf\n", sum2);
// Concatenate and print the String variables on a new line
// The 's' variable above should be printed first.
printf("%s %s", s, t);
return 0;
}
Considering your input-output examples, I amended your code like this:
char t[256]; // the string "is the best place to learn and practice coding!" MUST FIT!!!
...
scanf("%d", &value1);
scanf("%lf", &d); // NOT %d, %lf !!! &d or &e - I don't know - depends on you
scanf("\n%[^\n]", &t);
...
printf("%s%s", s, t); // you don't need a space, since your "s" already contains it.
Works fine for me.
UPD:
Now it actually works fine.
The reason your scanf() is failing to read the string is most likely that there's a newline character still in the stream that wasn't read off after you scanned the last number. "%[^\n]" tries to read a string, containing anything except a newline, and stops when an invalid character is reached; since the next character is a newline, there are no valid characters to read and it fails to assign the field. All you need to do to fix it is read the newline character before you scan the string.
Also, the %[ specifier does not need an s at the end -- it's a different conversion specifier from %s, not a modifier for it.
And finally, it's recommended that you specify the width for %[ or %s so that a long input string won't overrun the buffer you read the string into. The width should be the maximum number of characters to read before the null, so one less than your buffer size.
Using scanf(" %29[^\n]",t) will read off whitespace (including that newline) before scanning the string, and then scan a string with up to 29 non-newline characters (for a 30-char buffer).

Interactive, randomized program in C

My goal with this program is to incorporate the users inputs into a sort of interactive/randomized story but I'm not sure how I'm supposed to get the inputs from the users to fit between *ptrDescription, *ptrBeginning, *ptrMiddle, and *ptrEnd. Any help would be much, much appreciated!
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include <string.h>
#include <ctype.h>
int main(void){
int i;
char name[20];
char color[20];
int age;
char sentence[1];
//array of pointers to char arrays
char *ptrDescription[]={"the painfully handsome","the one and only","who seemed much older than"};
char *ptrBeginning[]={"was blissfully ignoring","could clearly see","had no idea"};
char *ptrMiddle[]={"the huge truck","the falling meteor","the bucket of milk","the mailman","the most powerful wizard"};
char *ptrEnd[]={"that was barreling toward them.","on the horizon."};
srand(time(NULL));
printf("Enter your first name: ");
scanf("%s", &name);
printf("\nEnter your age: ");
scanf("%d", &age);
printf("\nEnter your favorite color: ");
scanf("%s", &color);
for (i = 0; i < 1; i++)
{
//strcpy(sentence,ptrDescription[rand()%3]);
//strcat(sentence," ");
//strcat(sentence,ptrBeginning[rand()%3]);
//strcat(sentence," ");
//strcat(sentence,ptrMiddle[rand()%5]);
//strcat(sentence," ");
//strcat(sentence,ptrEnd[rand()%2]);
//strcat(sentence,".");
//sentence[0]=toupper(sentence[0]);
puts(sentence);
}
getch();
return 0;
}
EDIT:
I've edited a section of my code so that directly following for (i = 0; i < 1; i++) it now looks like this:
snprintf(sentence, sizeof sentence,"%s, %s %d year old, %s %s %s %s", name, ptrDescription[rand()%3], age,ptrBeginning[rand()%3], ptrMiddle[rand()%5], ptrEnd[rand()%2]);
There are tons of strange characters after the sentence in the output, like Japanese characters and stuff. I'm not sure why they're there, though. This is what it looks like exactly:
"Enter your first name: Justin
Enter your age: 20
Justin, the arrogant 20 year old, was purposefully ignoring the most powerful wizard that was barreling toward them. 汽$0HβHζ(テフフフフフフフフフフフフフH・(DキHH広$0陏&・汽$0タHζ(テフフフフフフフフフフフフフフフH WH・ H櫛H・t9HνHテ<"
Anyone know how I can get rid of them?
If you already have a name and an age, it's just a matter of inserting them into the correct place in sentence, right? So strcat(sentence, name) would work for name. age is a little trickier since you have to format the number first, and strcat won't do it for you. One solution would be to use sprintf(buf, "%d", age), and then concatenate buf (which is a scratch char array you would have to declare).
Any time you work with strings in C, you have to be concerned about having enough space in the target buffer. Your program can run out of space during both input and output. For the output, I would get rid of sentence altogether; since you just end up writing to stdout I would printf("%s", [part]) each part as you go along. For reading, scanf supports adding a length argument to the format string.
If you use one of the *printf functions, there are 2 things you must be careful about:
The arguments you pass are correct for the format string you use
Your buffer ends up null-terminated
Your current problem is with #1 - your format string promises 7 arguments to follow, but you only supply 6. snprintf grabs a "random" 7th value from the stack, interprets it as a char pointer, and copies whatever it finds there to sentence. You could see similar problems if your format string promised a char pointer but you placed an int in a given position. In this case the format string is a constant, so a smart compiler can validate that your format string matches the subsequent parameters. You'll want to get into the habit of taking compiler warnings seriously and not ignoring them.
The second point could be an issue if your sentence ended up bigger than your sentence buffer. If there is no room for a null-terminator, one won't be applied. You can check the return value of snprintf, or you can defensively always write a 0 to the last array position.

Is there a way to read a c-string and then an int with a single scanf in C?

Hey,
I'm trying to get this function to get the following output with the listed input, the "..." is where I'm not sure what to write:
void Question8(void)
{
char sentence[100];
int grade;
scanf(….);
printf("%s %d", sentence, grade);
}
Input:
My CS Grade is 1000
Output:
My CS Grade is 100
However, the kicker is that I need the scanf to read a c-string and then an int with a single scanf command, is this even possible?
Edit:
I can only edit the code in the location with the three periods ( "..." ), I cannot use anything more. I can assume that the input listed is expected but I cannot change anything outside of the three periods.
The output does not contain typos, the purpose of this assignment is to use flags and escape sequences.
It is possible to read pre-formatted string using scanf, however the format must be strict.
This version will continue to read the input until a digit is encountered and then read an integer.
Here is your code again:
char sentence[100];
int grade;
scanf("%[^0-9] %d",sentence,&grade);
printf("%s %d\n", sentence, grade);
I'll get this over with quick:
<obligatory_rant>
stupid question, but I guess it's homework and you're
stuck with these absurd limitations
</obligatory_rant>
Then, if you need to read everything up to but excluding the first digit, then the number:
if (scanf("%100[^0-9] %3d", text, &number) == 2)
...
Notes:
100 in "%100[... should be whatever your actual buffer size is to protect against buffer overrun.
The %3d documents that at most 3 digits should partake the the numeric value, so 1000 is correctly read as 100.
[^...] means the string made up of characters not ("^") in the following set, which is then specified as 0-9 - the digits.
if (... == 2) tests whether both positional parameters were scanned / converted successfully.
If you can't add an if and error message, then simply:
scanf("%100[^0-9] %3d", text, &number)
Tested in Visual Studio 2008
#include <stdio.h>
int main()
{
char sentence[100];
int grade = 0;
scanf("%[^0-9] %d",sentence,&grade);
printf("%s %d", sentence, grade);
return 1;
}
Input :
My CS Grade is 100
Output :
My CS Grade is 100
This is a really horrible question. A correct set of scanf parameters would be "%14c%3d", sentence, &grade
Because a space is included in the printf statement the trailing space needs to not be stored in sentence. Because the input contains other spaces there is no other solution (that I can thing of) than a fixed length. The integer parsing also requires a fixed length to truncate 1000 to 100.
I can think of no reason to ever write code anything like this. The code fits the requirements but wouldn't be useful in any other circumstances. I think that this is a very poor training exercise.

Resources