I decided to refresh my C by wring a simple little program. I tried to read in from a file "myfile.txt", apply operations and print to stdout. The file contains one line:
2 + 3
the output I expect is:
5
but I found this to be much more complicated than I originally expected. At first I tried using getc() but kept getting segfaults, then I tried fscanf() there is no output from addition to stdin except the print statement that prints:
2 1556274040
Why is the output 2 1556274040? And is there a better way to try to apply operations read form a file, like some apply() function that I can use?
Here's my code:
int main()
{
int ans, num1, num2;
char oper;
FILE *pFile;
pFile = fopen("myfile.txt", "r");
if (pFile != NULL) {
fscanf(pFile, "%d", &num1);
fscanf(pFile, "%c", &oper);
fscanf(pFile, "%d", &num2);
printf ("%d %c %d", num1, oper, num2);
if (oper == '+') {
ans = num1 + num2;
printf(ans);
}
fclose(pFile);
}
return 0;
}
printf(ans);
Not a valid syntax to print an int variable.
Try this -
printf("%d\n",ans);
As you ask
you can use fgets instead of using fscanf to read contents of file but make sure you check their return.
Here's a possible solution...
#include <stdio.h>
int main() {
int ans, num1, num2;
char oper;
FILE *pFile;
pFile = fopen("myfile.txt", "r"); // might need to specify binary/text
if (pFile != NULL) {
// fscanf(pFile, "%d", &num1); need spaces in format specifier.
// fscanf(pFile, "%c", &oper);
// fscanf(pFile, "%d", &num2);
// one way to solve...
fscanf(pFile, "%d %c %d", &num1, &oper, &num2);
fclose(pFile); // stopping some errors
printf ("%d %c %d = ", num1, oper, num2);
} // end if
else
puts("fopen returned NULL");
if (oper == '+') {
ans = num1 + num2;
printf("%d",ans);
} // end if
return 0;
} // end main
Related
I am making a program where the user enters two binary numbers and an operation character then I print the output in decimal. I want the while loop to keep the program running until the user enters quit. How can I read if the user enters quit and not an integer value in the scanf? Is there a way to catch this?
#include <stdio.h>
#include <string.h>
int toDecimal(int num);
int main(){
// Define variables
int num1, num2, result = 0;
char op;
char run[4] = "go";
// While loop to rerun program until quit is entered
while(strcmp(run, "quit\n") != 0){
// Reads user input
scanf("%i %c %i", run, &num1, &op, &num2);
printf("\nnum1: %i num2: %i op: %c\n", num1, num2, op);
num1 = toDecimal(num1);
num2 = toDecimal(num2);
printf("\nnum1: %i num2: %i op: %c\n", num1, num2, op);
}
printf("\nGoodbye!\n");
return 0;
}
I believe that I may be able to read everything in as a string and then convert to an integer however I don't know how. Is this a solution I should look into?
How can I read if the user enters quit and not an integer value in the scanf?
There is no good way with scanf(). Instead get user input with fgets() and do not use scanf() until you know why it is bad.
// Read user input
char buf[80]; // Use adequate size input buffer,
while (fgets(buf, sizeof buf, stdin)) {
buf[strcspn(buf, "\n")] = '\0'; // Lop off potential trailing \n
if (sscanf(bufm "%i %c %i", &num1, &op, &num2) == 3) {
printf("\nnum1: %i num2: %i op: %c\n", num1, num2, op);
num1 = toDecimal(num1);
num2 = toDecimal(num2);
printf("\nnum1: %i num2: %i op: %c\n", num1, num2, op);
} else if (strcmp(buf, "quit")== 0) {
break;
} else {
printf("Bad input <%s> ignored\n", buf);
}
}
This is a pretty basic idea , I hope you get the point.You could also use dynamic memory allocation when reading the string.
Basically you read the whole input with fgets and you extract the variables using sscanf.
#include <stdio.h>
#include <string.h>
int main ()
{
int n1,n2;
char arr[1000],oper;
fgets(arr,sizeof(arr),stdin);
while (strcmp(arr,"quit\n")!=0){
if (sscanf(arr,"%d %c %d",&n1,&oper,&n2)==3); /* Scanning for each number and operator and checking input*/
else
printf("wrong input");
/* Code */
fgets(arr,sizeof(arr),stdin);
}
return 0;
}
In C, I need to input four variables using scanf
scanf("%c %d %d %d", &v1, &v2, &v3, &v4)
the first variable may take two values 'c' and 'q'
when I enter c then I enter the other variables it will do some calculations but when I want to quit I should enter 'q' only and not enter the rest of the variables but scanf does not move forward until I enter the rest of the variables
is there anyway to solve it, I am not sure if it is possible using scanf but if there is another function then I don't mind using it
"is there anyway to solve it"
Read a line of user input with fgets() ...
char buf[100];
if (fgets(buf, sizeof buf, stdin)) {
.. and then scan it
char v1;
int v2,v2,v3;
int cnt = sscanf(buf, "%c %d %d %d", &v1, &v2, &v3, &v4);
if (cnt >= 1 && v1 == 'q') Quit();
else if (cnt == 4 && v1 == 'c') Do_stuff(v2,v3,v4);
else puts("Bad input");
You should use multiple scanfs for this. For example
scanf("%c", &v1);
if(v1 == 'c'){
scanf("%d %d %d",&v2, &v3, &v4);
/*some staff*/
}
else{
/*another staff*/
}
I have this file:
0 -> 1:50 2:30 3:10
1 ->
2 -> 0:10 3:20
3 -> 1:20 2:10 3:30
And I want to extract all the numbers from the file with this code:
int a, b, c;
while (fscanf(fp, "%d ->", &a) == 1) {
printf("%d ->", a);
while (fscanf(fp, " %d:%d", &b, &c) == 2) {
printf(" %d:%d", b, c);
}
printf("\n");
}
The idea is that on the first loop it will scan the first number followed by space followed by -> and then the inner loop will scan the following sequence of " %d:%d" until the end of line which will then make the outer loop return 1 because it could successfully read "%d ->".
Ouput of code:
0 -> 1:50 2:30 3:10
It seems like it doesn't work as expected, and the outer while loop exits when it tried to read the number 1 from the second line(but it should?). I just find this weird because I've done something similar recently and it was working fine.
After removing the loops and replacing with this code I get the correct results so it had something to do with my loops:
fscanf(fp, "%d ->", &a);
fscanf(fp, " %d:%d", &b, &c);
fscanf(fp, " %d:%d", &b, &c);
fscanf(fp, " %d:%d", &b, &c);
fscanf(fp, "%d ->", &a);
fscanf(fp, "%d ->", &a);
fscanf(fp, " %d:%d", &b, &c);
fscanf(fp, " %d:%d", &b, &c);
fscanf(fp, "%d ->", &a);
fscanf(fp, " %d:%d", &b, &c);
fscanf(fp, " %d:%d", &b, &c);
fscanf(fp, " %d:%d", &b, &c);
An iteration of while (fscanf(fp, " %d:%d", &b, &c) == 2) { is consuming the "\n1" in "\n1 ->". This fouls the following fscanf(fp, "%d ->", &a), which starts at " ->" and stops the loop.
Code needs to detect the '\n'. format directives/specifiers like " " and "%d" consume end-of-line without reporting that.
Direct solution: As the file is lines of data, then read lines of text with fgets().
Use "%n" to record offset of scan.
// Generous maximum line size
#define LINE_N 1024
char line[LINE_N];
while (fgets(line, sizeof line, fp)) {
int a;
int n = 0;
// v--- space needed to consume trailing whitespace
sscanf(line, "%d -> %n", &a, &n) == 1) {
if (n == 0) {
fprintf(stderr, "Invalid line '%s'\n", line);
continue;
}
printf("%d ->", a);
char *p = line + n;
while (*p) {
int b,c;
n = 0;
// v--- space needed to consume trailing whitespace
sscanf(p, "%d:%d %n", &b, &c, &n);
if (n == 0) {
fprintf(stderr, "Invalid rest of line '%s'\n", p);
break;
}
printf(" %d:%d", b, c);
p += n;
}
printf("\n");
}
The algorithm isn't handling the newlines. So it gets stuck and the end of the first line and isn't able to read anything matching n ->.
One way that works reliably for all C RTL implementations is to use fgets() to read each whole line (including the newline at the end) and then use sscanf() to parse the string.
I think you just need to fseek one char ( newline ) at the last printf.
I'm getting an error:
Type invalid operands to binary & (have 'int *' and 'int')
here is my program. The problem occurs at line 34 or the fscanf num1
#include <stdio.h>
#include <stdlib.h>
FILE *infile;
FILE *prnt;
main()
{
int num1, num2, nums;
char complex;
float fcost;
char name [11];
infile = fopen ("F:/DATA.txt", "r");
prnt = fopen ("F:/income.txt", "w");
if (infile == 0)
{
printf ("FILE NOT ON DISK\n");
system("pause");
return 0;
}
fprintf (prnt, "%-15s %-23s %6s\n\n", "ABAHLMAN", "Program 1", "PAGE 1");
fprintf (prnt, "\n");
fscanf (infile, " %i %i %i %f %c", &nums &num1 &num2 &fcost &name);
while (!feof (infile))
{
int area = (nums * 200) + (num1 * 300) + (num2 * 450);
float cost = fcost + (area * 75.00);
double income = 12 * ((nums *450) + (num1 * 550) + (num2 *700));
float payback = cost/ income;
fprintf (prnt, "%-10s %5f %7c %9.2f\n", name, payback, area, cost);
fscanf (infile, " %d %d %d %f %c", &nums &num1 &num2 &fcost &name);
}
fclose (infile);
fclose (prnt);
return 0;
}
You are not separating the arguments with comma in fscanf() statements. They should be:
fscanf (infile, " %i %i %i %f %s", &nums, &num1, &num2, &fcost, name);
and
fscanf (infile, " %d %d %d %f %s", &nums, &num1, &num2, &fcost, name);
Note that name is an array and it gets converted into a pointer when you pass it to fscanf(). So, the & operator needs to be dropped. As noted in the comments, the format should be %c for name.
Also, see: What is array decaying?
I'd also suggest to use a standard definition for main() function. main() {..} is outdated and should be avoided.
Instead, you can write it as int main(int).
I see a few problems. First, no commas to separate the arguments for scanf.
Next, the last argument for fscanf should have %s format and be passed name without &.
Next, feof is not the way to control a loop, you should check the return value from fscanf anyway.
You also use the wrong format specifier %c for area in printf which should be %d
Finally be consisent with the use of %d or %i format specifier. Unless you want the user to input in other number bases than decimal, stick to %d.
So I suggest the loop should be
while (fscanf (infile, " %d %d %d %f %s", &nums, &num1, &num2, &fcost, name) == 5)
{
int area = nums * 200 + num1 * 300 + num2 * 450;
float cost = fcost + area * 75.00;
double income = 12 * (nums * 450 + num1 * 550 + num2 * 700);
float payback = cost / income;
fprintf (prnt, "%-10s %5f %7d %9.2f\n", name, payback, area, cost);
}
I am learning the switch statement of C. This is my small program and it runs and does the calculation but doesn't let me see the result of the operation. The black window shows up so that I input the numbers and the operator and then for a fraction of a second shows the result and disappears. Any help is appreciated.
#include <stdio.h>
int main(int argc, char *argv[])
{
int num1, num2, ans=0;
char ch, name;
printf("Enter a value: ");
scanf("%d", &num1);
printf("Enter a second value: ");
scanf("%d", &num2);
printf("Input * To multiply\
+ To add\
- To subtract: ");
scanf(" %c", &ch);
switch(ch)
{
case'*':
ans=num1 * num2;
printf("%d times %i equals: %i",num1,num2,ans);
break;
case'+':
ans=num1+num2;
printf("%i plus %i equals: %d",num1,num2,ans);
break;
case'-':
ans=num1-num2;
printf("%d minus %d equals: %d",num1,num2,ans);
break;
default:
printf("Range numbers");
}
getchar();
return ch;
}
Probably due to output buffering. Add newlines (\n) last in your formatting strings.
As a newbie, you should end all your printf format string with an escaped newline \n, i.e. printf("%i plus %i equals %d\n", num1, num2, ans); (or you should call fflush(stdout); just after the end of the switch before the getch and before all your scanf).