Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
We got an assignment to make a program to read what is written inside our text file (name, student number, course, year, section, etc.. etc..) But I can't seem to make it work, can you tell me what's wrong?
#include <windows.h>
#include <conio.h>
#include <stdio.h>
struct record
{
char name[50],number[50],course[50],gender;
int year, section;
float midterm,final,average,sum;
};
int main()
{
int a=1,n;
int passed=0,failed=0;
FILE *fp;
fp = fopen("BSU.txt","r");
if(fp==NULL)
{
printf("ERROR!");
getch();
}
struct record student[25];
printf("Please input the number of students: ");
scanf("%d", &n);
for(a=0;a<n;a++)
{
fscanf(fp, "%f", student[a].average);// I CANNOT MAKE THE FSCANF WORK!!//
}
getch();
}
It should be
fscanf(fp, "%f", &student[a].average);
instead of
fscanf(fp, "%f", student[a].average);
But this allows you only to read a file containing numbers, for example:
1.5
1.9
2.7
The file you want to read is more compilcated.
So in your for loop you need to read 10 lines, extract the relevant information from each line, store that information in the corresponding field of your record, and store the record somewhere.
You need to consider the input file format.
When you're calling fscanf the 'cursor' is located at the first line of your file. What you need to to is to bring the cursor to the line you want to read.
Student Name: Andrea Zoelle Jacinto <-- cursor is located at the beginning of this line
Gender: M
Student Number: 2015-04711-MN-0
Course: BSIT
Year: 1
Section: 2
Midterm Grade: 2.00
Final Grade: 1.75
Average Grade: 1.8 <-- you need the cursor here
To achieve that you can use fgets in an while loop to get rid of the lines before the desired line.
char line[256];
while( fgets(line, 256, fp) && line[0] != 'A'); // line[0] != 'A' makes the loop stop when it reached the desired line
Now your cursor is at the desired line, however you need to get rid of the text in front of the value you want to read.
Average Grade: 1.8 <-- get rid of "Average Grade: "
The good thing is line already contains this line, so you can use sscanf to read formatted from this string.
sscanf(line, "%*s %*s %f", &student[0].average); // note the ampersand in front of student[0].average to get its address
Using %*s makes sscanf ignore the words "Average" and "Grades:" so %f will read the desired value.
Because it looks like your homework, I will not give you the solution but I tell you where is bug.
You are using fscanf in the incorrect way. This line:
fscanf(fp, "%f", &student[a].average);
is telling something like: "take somevalue (float type) and write it to student[a].average".
It can't work in your situation, because your data structure is more compilacted.
What have you to do?
First, try to write all data from the file on output.
After that, you should try to parse the line which are you interest :)
Read about getline, sscanf. It could be very helpful for you :)
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
So this is my code, and...
#include <stdio.h>
int main()
{
int order, stock;
char credit;
printf("\nEnter order value: ");
scanf("%d", &order);
printf("Enter credit (y/n): ");
scanf("%s", &credit);
printf("Enter stock availabilty: ");
scanf("%d", &stock);
if (order <= stock && credit == 121 || credit == 89)
{
printf("Thank you for ordering from us, the items will be shipped soon.\n\n");
}
else if (credit == 78 || credit == 110)
{
printf("Your credit is insufficient, hence as per company policy we cannot ship your ordered items.\n\n");
}
else if (order > stock && credit == 121 || credit == 89)
{
printf("We're falling short on supply, hence we'll ship the items we have in stock right now.\nThe remaining balance will be shipped as soon as stock arrives.\n\n");
}
else
{
printf("Invalid data.");
}
return 0;
}
... this was my input:
Enter order value: 12
Enter credit (y/n): Y
Enter stock availabilty: 10
The expected output was supposed to be:
We're falling short on supply, hence we'll ship the items we have in stock right now. The remaining balance will be shipped as soon as stock arrives.
However the program printed this:
Thank you for ordering from us, the items will be shipped soon.
Can someone explain me why this happened??
The line
scanf("%s", &credit);
is wrong.
The %s format specifier expects a pointer to the address where it should write the input as a string. When doing this, you must ensure that there is sufficient memory in that location to write the string.
However, at the specified memory location, there is only space for a single character, because with the line
char credit;
you only declared a single character.
For storing the string "Y", you need at least space for two characters, one for the character Y and one for the terminating null characer of the string. In C, strings always have a terminating null character at the end.
Of course, it would be possible to could solve this problem by adding space for a second character, and limiting the number of matched characters to 1, in order to ensure that there will be enough space for storing the string.
char credit[2];
[...]
scanf( "%1s", credit );
However, I do not recommend this solution. Instead, I recommend that you use the %c format specifier instead of the %s format specifier. The %s format specifier is intended for entire strings, whereas the %c format specifier is intended for individual characters.
Therefore, this solution would probably be better:
char credit;
[...]
scanf( "%c", &credit );
However, this solution has one problem. The previous function call to scanf
scanf( "%d", &order );
will not have consumed the entire previous line, but will only consume as many characters as possible to match the number. All characters that are not part of the number, including the newline character, will be left on the input stream.
Therefore, if you call
scanf( "%c", &credit );
afterwards, the %c format specifier will probably match the newline character, instead of the Y in the next line. See this question for further information on this problem:
scanf() leaves the newline character in the buffer
In order to solve this problem, you can instruct scanf to first discard all whitespace characters (newline characters are whitespace characters), before attempting to match the %c format specifier:
scanf( " %c", &credit );
Another way of solving the problem of leftover characters would be to use fgets instead of scanf. This solution has the advantage that the behavior of that function is more intuitive, as it normally reads exactly one line of input per function call. In contrast to scanf, it does not normally leave leftovers of a line on the input stream. See this guide for further information:
A beginners' guide away from scanf()
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
How would I read information from a file to variables if I don't know how long it's gonna be.
Example of file:
student name
class grade credits
class grade credits
class grade credits
How would I save this info from this file if the number of classes varied. I need to print this information to the screen, while using the grades and number of credits to calculate a students GPA.
As proposed by fluter, fgets will allow you read the file line by line. getline is another (better IMHO) solution, it's manpage provides a simple usage example.
Then inside the reading loop, you have several options. I suggest you sscanf applied on the line read.
It returns the number of items read. In this kind of simple case, I usually try to scan the line with different format strings and check the number of items read to verify if the line matched.
For example, you could use something like:
"%s" as the format string for student name lines
"%s %c %d" as the format string for grade lines
And I suggest you to compute the GPA inside the loop, this way, you shouldn't have to store the grades, if I'm correct.
The usual way to do is to scan the input file until it meet the end of file or EOF, so you know you have reached the end of the file.
Something like this:
FILE *fp = fopen("grade.txt", "r");
if (!fp) { exit(1); }
char line[1024];
char name[1024];
char *s;
s = fgets(line, sizeof line, fp);
if (!s) { fclose(fp); exit(0); }
strcpy(name, line);
do {
s = fgets(line, sizeof line, fp);
// convert line to grade, to integer or double as you want
} while (s != NULL);
// compute the GPA
I'm new to coding in general, and very new to C.
I'm trying to write a program in c that asks the user for input and based on that users input, prints specific text to a .txt file. Please have a look at my code and let me know what I'm doing wrong.
Please have a look at my code below. Thanks very much for your assistance.
Matt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * fptr;
int main(){
char name[32];
char partNum[32];
char desc[250];
char ans1;
char ans2;
char sn[50];
char ansRep;
fptr = fopen("C:\\Users\\mgreene\\Documents\\EmailTemplates\\QCIssue.txt", "w");
if (fptr ==0)
{
printf("Error--file could not be opened\n");
exit(1);
}
printf("What is the customer's first name?\n");
scanf("%s", name);
printf("With which Part number is the user experiencing difficulties?\n");
printf("Enter Part Number:");
scanf("%s", partNum);
printf("Please enter a brief description of the problem\n");
scanf("\n%s", desc);
printf("Does the product have a serial number?\n");
scanf("%c", &ans1);
if (!strcmp(&ans1, "y")== 0)
{
printf ("Do you know the serial number?\n");
scanf("\n%c", &ans2);
if (!strcmp(&ans2, "y")==0)
{
printf ("Please enter the SN:\n");
scanf("\n%s", sn);
fprintf(fptr, "\nHi %s,\n\nI hope this message finds you well.\n\nI write to you today as the Quality Manager at Blank. I received a report that you're experiencing difficulties with part: %s, %s; specifically, the report indicates that %s. Is that an accurate description of the problem? Firstly please accept my apologies on behalf of Blank for the difficulties you're experiencing with this part. As an ISO9001:2008 compliant organization, Blank takes all issues related to customer satisfaction very seriously. It is our intention to resolve this matter as soon as is possible.\n\n", name, partNum, sn, desc);
}
else
{
fprintf(fptr, "\nHi %s,\n\nI hope this message finds you well.\n\nI write to you today as the Quality Manager at Blank. I received a report that you're experiencing difficulties with part: %s; specifically, the report indicates that %s. Is that an accurate description of the problem? Firstly please accept my apologies on behalf of Blank for the difficulties you're experiencing with this part. As an ISO9001:2008 compliant organization, Blank takes all issues related to customer satisfaction very seriously. It is our intention to resolve this matter as soon as is possible.\n\nBefore I can begin an investigation into this problem, I'll need the serial number from that unit. Can you please forward me the serial number as soon as you're able? Once I have that, I can begin the investigation on our end. Thanks.\n\n", name, partNum, desc);
}
}
else if (strcmp(&ans2, "y")==0)
{
printf("Will Blank be sending the customer a replacement? Please enter y or n\n");
scanf("\n%c", &ansRep);
if (!strcmp(&ansRep, "y")==0)
{
fprintf(fptr, "Blank can send you a replacement product as soon as is possible. In order to ensure that the replacements are shipped to the correct address, will you please confirm you shipping address via email? Thanks.\n\n");
fprintf(fptr, "Thank you for your assistance in resolving this matter. Please let us know if you have any additional questions, comments, or concerns about this specific issue or any issues related to products distributed by Blank.\n\n");
fprintf(fptr, "Have a great day!");
}
else
{
fprintf(fptr, "Thank you for your assistance in resolving this matter. Please let us know if you have any additional questions, comments, or concerns about this specific issue or any issues related to products distributed by Blank.\n\nHave a great day!");
}
}
fclose (fptr);
return (0);
}
if (!strcmp(&ans1, "y")== 0) is wrong, which may be modified to if(ans1 != 'y'). You should do similar modifications to if (!strcmp(&ans2, "y")==0), if (strcmp(&ans2, "y")==0), if (!strcmp(&ansRep, "y")==0) in your code.
And for scanf("%c", &ans1);, you may rewrite it as follows:
scanf(" %c", &ans1);
Removing \n in scanf("\n%s" [...] and adding a space before %c in scanf("%c" and scanf("\n%c" (removing \n) may help.
you could create a simple function to catch strays from scanf
void clear_input_buffer(void)
{
char buffer[100];
fgets(buffer, 100, stdin);
}
then include it after scanf
scanf("%s", name);
clear_input_buffer();
First things first: ans1 and ans2 are chars; you are doing strcmp(&ans2, "y") - here, "y" is a string (NULL terminated array of characters) because it is in double quotes. Before anything else, you should replace all your comparisons of those variables with something like
if(ans1 == 'y')
Also, when you read a character you should add a space in front of the %c just in case there is some whitespace or a stray new line from previous input - scanf(" %c", &ans1);
Short answer: I think your strings contain garbage!
Strings in C must be terminated by a Null byte ('\0'). When you create a char array on the stack (or heap) the contents of that array may be filled with whatever junk your memory happened to have at the time. Try running this small program to see what I mean. One might predict this program will print 3 blank lines, but it should instead print 3 lines of random garbage (every time you run this program the garbage should be different).
#include <stdio.h>
int main(){
char name[32];
char partNum[32];
char desc[250];
printf("%s\n", name);
printf("%s\n", partNum);
printf("%s\n", desc);
}
There are a few things you could improve in the program you've posted, but to specifically address your string containing garbage, here is a simple solution:
Replace lines like char name[32]; to char *name = calloc(32, sizeof char); and be sure to free these memory allocations at the end of your program like this free(name).
calloc sets all the memory it allocates to NULL so your strings will no longer contain garbage.
If you are experiencing garbage in your output file, that should do the trick.
Also note
You are using fixed size char arrays. What happens if a user decides to type something in thats longer than you expected? The input will bleed into other parts of memory and can affect the values of other variables.
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 8 years ago.
Improve this question
code isnt working on line 19 & 20
i'm trying to get a string named hotel...
when i put gets(hotel) almost over everything surprisingly code starts working...but not in the middle of the code.!!!!!
#include<stdio.h>
main()
{
char topping[24];
char hotel[50];
int slices;
int month,day,year,i;
float cost;
printf("how much a pizza cost in your area? ");
printf("enter in $XX.XX\n");
scanf("$%f",&cost);
printf("what is your favorite one word pizza topping?\n");
scanf("%s",&topping);
printf("how many slices of %s of pizza \n",topping);
scanf("%d",&slices);
printf("which is your favorite hotel in town?\n");
gets(hotel);
printf("what is today's date (enter in XX/XX/XXXX format)\n");
scanf("%d/%d/%d",&day,&month,&year);
printf("\n\n\n\n\nwhy not treat yourself %d slices of %s pizza in %s on %d/%d/%d it will cost you only %.2f",slices,topping,hotel,day,month,year,cost);
return 0;
}
This is the same thing I talked about recently here: D lang - Using read and readln() in the same program although in C instead of D so the solution is slightly different but same explanation.
The scanf stops on whitespace, which is a newline... which gets sees as the end of input and thus reads an empty line.
The solution is to consume that newline before continuing:
printf("how many slices of %s of pizza \n",topping);
scanf("%d",&slices);
fgetc(stdin); // ADDED THIS LINE TO READ PAST THE NEW LINE CHARACTER
printf("which is your favorite hotel in town?\n");
gets(hotel);
PS don't use gets, use fgets(hotel, 50, stdin); instead. The 50 there is the size of the buffer, ensuring it doesn't overflow.
There are a couple of things I would change.
When you are reading topping & hotel, they are strings, you do not need to pass that by reference. So pass scanf("%s", topping);
When you are doing the strings, you want to make sure you don't allow the user to overfill the array. See this for an example of how to limit the input size.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Right so i have a program that will find a strings place in a file, and the line it belongs to. Now the Find works fine but the string compare has a big problem i cannot get my head around, here is the code:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main(void){
int loop, line;
char str[512];
char string[512];
FILE *fd = fopen("Student Passwords.txt", "r");
if (fd == NULL) {
printf("Failed to open file\n");
return -1;
}
printf("Enter the string: ");
scanf("%s",string);
printf("Enter the line number to read : ");
scanf("%d", &line);
for(loop = 0;loop<line;++loop){
fgets(str, sizeof(str), fd);
}
printf("\nLine %d: %s\n", line, str);
str[strlen(str)-1] = '\0';
if(strcmp(string,str) == 0 )
{
printf("Match");
}
else
{
printf("Nope");
}
fclose(fd);
getch();
return 0;
}
Someone told me to use strlen, which i of course inserted into the code but i think it just makes it worse, i am not sure what to do now can i have some help?
Text file:
Password
abcdefg
Star_wars
jedi
Weapon
Planet
long
nail
car
fast
cover
machine
My_little
Alone
Love
Ghast
Thanks
Edit: Input: Random word , Input: line number. Program will go to the line chosen and scan the string stored there, and compare it with the input string. Output: Either Match or Nope.
Edit: Input: Password, 1 Output: Match , Input: Password, 2 Output: Nope.
Your program works fine for me except that your text file have trailing spaces after some words. but your user input do not have spaces. Try to print the lengths of the user input and read line and you can find out.
Remove all trailing spaces from your text file and there should not be any problem.
Also as others have mentioned, it is good to use similar input functions in your code. you can use fgets for user input also.