Error in reading the file in C [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm trying to write and read from file. writing works fine, but when it tries to read, the program crashed. tell me whats the error?
The objective of this program is to store the record of students in a file.
Calculate the percentage, and find the highest and lowest percentage of student.
#include <stdio.h>
#include <conio.h>
#include <string.h>
struct result
{
char name[15];
int batchNo;
int rgtNo;
int marks;
float perc;
};
int main()
{
char answer, i = 1;
FILE *ptr, *abc;
result s, st;
int j;
ptr = fopen("rec.txt","a");
abc = fopen("rec.txt","r");
if(!ptr)
printf("Error opening file");
else if(!abc)
printf("Error opening read file");
else {
do
{
int sum = 0;
printf("\nEnter name of student %d: ", i);
scanf("%s", s.name);
printf("\nEnter Batch #: ");
scanf("%d", &s.batchNo);
printf("\nEnter Registeration no: ");
fflush(stdin);
scanf("%d", &s.rgtNo);
printf("\nEnter marks of Five subjects: ");
scanf("%d",&s.marks);
/*for(j = 0; j < 5; j++)
{
scanf("%d",&s.marks[j]);
sum += s.marks[j];
}*/
s.perc = sum / 5.0;
printf("Percentage of student %d: %f", i+1, s.perc);
fprintf(ptr, "%s %d %d %d %f", s.name, s.batchNo, s.rgtNo, s.marks, s.perc);
printf("\n\n\n");
printf("Do you want to add another record? (y/n) ");
answer = getche();
i++;
} while(answer == 'y');
printf("outside loop\n");
fclose(ptr);
fflush(stdin);
rewind(abc);
do
{
fscanf(abc, "%s%d%d%d%f", s.name, s.batchNo, s.rgtNo, s.marks, s.perc);
printf("in loop");
} while( !feof(abc));
fclose(abc);
}
}

So many defects, so little time.
C is not C++
They are two different languages. Remove the C++ tag.
But since you tagged it as C++, you should use the fstream and iostream libraries as well as the std::string type.
One pointer per physical file
You have one FILE * for each different mode of the same file. In many cases, this will confuse the operating system and heck some won't allow it.
Instead, use one FILE * and open the file as rw+ for read, write and append.
See fseek function.
Buffer overflow with scanf
You have reserved 15 letters for the name. What happens if the user types in a name longer than 15 letters? Buffer overflow. You could write over other variables that follow the name member.
You could resolve this by using fscanf with the C language or std::cin and std::string with the C++ language.
Flushing the input
The flush function only works with output buffers. Don't use with input streams.
In the C language you have to read characters until the buffer is empty or until your terminator character is found (such as 'n').
In C++ this is accomplished by cin.ignore(1000000, '\n').
Checking input functions for errors
You can't trust the User. You must check the scanf return value for errors. If you ask for a number and the User types in a number, the scanf will fail. The value is undefined.

the program crashes whenever you type something different than 'y' at the last question Do you want to add another record? (y/n).
think what happens after this stage in your program...
hint - take a look at your ptr and abc File pointers - do they point to the same file?

The issue which makes your program segfault is the fscanf call: you're supposed to pass pointers to variables for arguments. I guess you quickly C&P without double checking your code.
As mentioned in another answer: fflush behaviour isn't specified for input streams, though many implementations behave as you expect. Another way to flush is to do a loop on the stream and read char by char:
void flush_stdin(){
char c;
while (c != '\n' && c != EOF)
c = getchar();
}
Note: I'm using getchar, as getche isn't available on my system. I suppose you should have it too, and would recommend using it for portability.
Regarding multiple opening of the same file in different modes: I don't think it should be a problem, though it seems much more straightforward to open it in append mode first, close it when the input session is done, and then reopen it for reading afterwards. In a more complex program, you'd probably split these two functionalities in separate functions, each doing its own I/O, thus following that pattern.
One last thing: you probably want to test the result of your calls to scanf and the like. Perhaps a small macro like the following would help:
#define CHECK_SCAN(x) do { \
int err = (x); \
if (err <= 0) { \
printf("error on scan: %s", strerror(err)); \
exit(1); \
} } while(0)

Related

Why does scanf_s() isn't working second time I am calling it in order to verify if user provided correct input?

I am writing an application with a menu and I am asking the user to provide an integer representing an option
from the menu
1. Option 1
2. Option 2
3. Option 3
...
This option is stored in a variable called
option
I want to avoid wrong input such as "12a", "1a2", "anyString" and I've read that this can be achieved by storing return value of scanf_s() function.
So I stored it in a variable called
ret
and now I want that every time user provides wrong input to prompt them to enter a new value.
So I wrote something like this:
int ret = scanf_s("%d", &option);
while (!ret)
{
cout << "Provide an integer, not a string! :)\n";
ret = scanf_s("%d", &option);
}
The problem is when it enters the while it is not allowing user to enter a new value and hence the value of ret never changes, making it run endlessly.
How can I achieve what I am looking for?
When scanf_s fails to convert an integer, the offending input stays in the input stream. Calling scanf_s("%d", &option) again will produce the same result until some characters are removed from the input stream. Note also that using scanf_s or scanf directly from stdin is error prone: the newline entered by the user stays in the input stream and will be read by a subsequent call to getchar() or fgets(), potentially causing unexpected behavior.
To avoid these pitfalls, it is recommended to read one line at a time with fgets() and convert it with sscanf() this way:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
int main() {
char buf[80];
int option;
char cc;
for (;;) {
print_menu(); // output the menu options
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: break from the loop */
break;
}
/* parse exactly one integer with optional leading and trailing whitespace */
if (sscanf(buf, "%d %c", &option, &cc) != 1) {
printf("invalid input: %s", buf);
printf("enter one integer exactly\n");
continue;
}
printf("option is %d\n", option);
// handle option
}
return 0;
}

How to keep taking values from the user in C but stop when the user does not enter any value and presses enter?

int k;
vector<int>v;
while ((scanf("%d", &k)) != EOF) {
if (v.size() > 20) break;
else {
if (k > 0 && k <= 120) v.push_back(k);
}
}
**The above snippet is taken from codechef blogs **
<rant>Never tag a question both C and C++ on SO again. It is reserved for questions about interoperations or very specific language-lawyer points, and should not be used for code that could be more or less used on both languages. In that latter case choose one in your first question and if you later need it ask a new question for the other language</rant>
Your problem is that for the scanf family questions spaces and newlines are just ignored when you use a %d conversion character. And scanf returns the number of elements that could be decoded and only stops on an end of file, read error or conversion error.
If you want to be able to detect an empty input, you will have to use fgets + sscanf from the C standard library, or getline + stringstream from the C++ one.

Unable to find errors - Turbo C

I am making a simple program to add two numbers. I've done everything correct but somehow it's showing an error.
I am using TurboC for windows7 64bit (downloaded from filezilla)... I've also used devcpp but but there its showing error in using void main()... Why this is so? Why it is not working?
Also, can anybody suggest some good software for programming console-based for projects C, C++, etc.?
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
int num1=0,num2=0;
//printing hello world
//printf("Hello World!");
printf("Enter number 1 : ");
scanf("%d",num1);
printf("Enter number 2 : ");
scanf("%d",num2);
int num3 = num1+num2;
printf("The sum of %d and %d is %d",num1,num2,num3);
getch();
}
The problem is with your scanf(). When accepting values, you must add the & before the variable. The unary & returns the address of the variable next to it, and scanf() then stores the value at that address. But note that you do not need to use & in printf() unless you actually want to print the address. In short, change your scanf() 's to
scanf("%d",&num1);
and
scanf("%d",&num2);
Here's your working code code
#include<stdio.h>
int main()
{
int num1=0,num2=0;
//printing hello world
//printf("Hello World!");
printf("Enter number 1 : ");
scanf("%d",&num1); // see here
printf("Enter number 2 : ");
scanf("%d",&num2); // and here
int num3 = num1+num2;
printf("The sum of %d and %d is %d",num1,num2,num3);
}
The error with void main() is that it is no longer accepted. On older versions like TurboC, you can use void main(), but the standard clearly states that we should not use void for main(), instead you should use int main().
Read this for reference
What should main() return in C and C++?
And, don't use <conio.h>. It's not supported in the standard. If you want to clear the screen, add the header file <stdlib.h> and use system("cls");
Regarding a replacement for getch(), you can just use getchar(). ( although in some programs, you will have to use two or more getchar()'s )
There's one thing you should know, and that is that both TurboC and DevC++ are outdated.
You should probably get Code Blocks.
You get the "Declaration not allowed here" error because prior to C99 ( your IDE TurboC runs on an older version than C99 ) , variables had to be declared at the beginning of a block. You can use Declaration not allowed here error in C as reference
I'm only focusing on the error:
printf("Enter number 1 : ");
scanf("%d",&num1); //use & for input
printf("Enter number 2 : ");
scanf("%d",&num2); //use & for input
When you use scanf(), you must provide the address of the variable you write to using &.
scanf("%d",num1);
should become:
scanf("%d",&num1); //add the & to refer to the address

Query regarding SPOJ TEST

I might be wrong in asking an SPOJ problem on this forum but I wanted to understand one mechanism which I wanted to know from the enriched community here.
Your program is to use the brute-force approach in order to find the Answer to Life, the Universe, and Everything. More precisely... rewrite small numbers from input to output. Stop processing input after reading in the number 42. All numbers at input are integers of one or two digits.
Example
Input:
1
2
88
42
99
Output:
1
2
88
My Solution:
#include <iostream>
using namespace std;
int main()
{
int n,i=0;
int a[100] = {0};
while((cin>>n))
{
a[i] = n;
i++;
continue;
}
for(int j = 0;a[j]!=42;j++)
cout<<a[j]<<endl;
return 0;
}
Good Solution:
#include <iostream>
using namespace std;
int main()
{
int n;
while(true)
{
cin>>n;
if(n == 42)
break;
cout<<n<<endl;
}
return 0;
}
My query is what happens to the input in the good solution?We would be running the loop only till the number is not 42.How does Good solution handle the remaining input?I got some hint that it is somewhat related to buffering and all.Please provide me some explanation or links or study material or at least some keyword to google etc to get clarity on this.
Remaining input in good solution will be ignored by "good solution".
If you need more info read:
object
std::cin
extern istream cin;
Standard input stream
Object of class istream that represents the standard input stream oriented to narrow characters (of type char). It corresponds to the C stream stdin.
The standard input stream is a source of characters determined by the environment. It is generally assumed to be input from an external source, such as the keyboard or a file.
object
stdin
FILE * stdin;
Standard input stream
The standard input stream is the default source of data for applications. In most systems, it is usually directed by default to the keyboard.
stdin can be used as an argument for any function that expects an input stream (FILE*) as one of its parameters, like fgets or fscanf.

user initiated looping in c++ [duplicate]

This question already has answers here:
How to do scanf for single char in C [duplicate]
(11 answers)
Closed 8 years ago.
I would like to write a program that takes a input from the user and calculates the triangular number. There should also be an option to ask the user if he wants to take another input or exit and that needs to be done using while or do...while. I have the following code written but doesn't do what is intended:
#include <stdio.h>
int main(void)
{
int n, number, triangularNumber;
char s = 'Y';
while (s == 'Y') {
printf("What triangular number do you want? ");
scanf("%i", &number);
triangularNumber = 0;
for (n = 1; n <= number; ++n)
triangularNumber += n;
printf("Triangular number %i is %i\n\n", number, triangularNumber);
printf("Do you want to continue?\n");
scanf("%c", &s);
}
return 0;
}
The above code only does it once after which it exits. How can I make it run the loop again based on the input I give? Thanks in advance.
scanf("%i",&number); generates a newline that is consumed by your scanf("%c",&s);
Rewrite as scanf(" %c",&s) (contains a space before %c) to ignore all whitespace before input.
Two problems: First of all there is a difference between small and capital letters, 'y' != 'Y'.
The second problem, and what you are seeing here, is that the first scanf where you read the number, it leaves the newline in the input buffer. Then the second scanf call reads that newline and writes it to the variable s.
The first problem can easily be solved by making sure the contents of the variable s is a capital letter, by using toupper:
while (toupper(s) == 'Y') { ... }
The second problem can be just as easily fixed by asking scanf to read and discard leading whitespace when getting the character, this is done by simply adding a space before the format code:
scanf(" %c", &s);
// ^
// |
// Note space here