First time working with C and I was asked to do a simple average function WITHOUT scanf (only using getchar) for my Systems class. I ended up writing an unnecessarily complicated loop just to get my code to compile and even after compiling+running it doesn't seem to do anything after taking in the keyboard input.
#include <stdio.h>
#include <stdlib.h>
//average program
//use getchar to get numbers separately instead of scanf and integers.
//Not sure why. Most likely to build character.
int main (int argc, const char * argv[])
{
char x,z;
float avg;
int tot,n,b;
printf("Input Integer values from 1 to 100. Separate each value by a space. For example: 23 100 99 1 76\n");
ret:
x=getchar();
while( x != '\n' );
{
if(x==isspace(x))
{ goto ret;}
opd:
z=getchar();
if ((z == isspace(z)))
{
b = x - '0';//subtracting 0 from any char digit returns integer value
tot +=b;
n++;
goto ret;
}
else if(z == '\n')
{
b = x - '0';
tot +=b;
n++;
goto end;
}
else
{
x = x*10;
x = x + z;
goto opd;
}
}
end:
avg=tot/n;
printf("Taking of the average of the values. The average is %1.2f\n",avg);
return avg;
}
The semicolon in while(...); causes an infinite loop, it's the same as saying: while(...) continue;
You should use only one loop, and you should try to use only one call to getchar() ... it's too confusing with multiple getchar() calls and your code is trying to throw away the first line the way it's written.
Definitely get rid of the goto statement, your instructor won't like them and they are quite unnecessary. (Do read up on break and continue.)
In C parsers calling getchar() directly, it's useful to be able push a character back on the input stream. See man 3 ungetc or just write a simple wrapper around getchar(). You should only need one character of pushback at the end of a parser loop.
Related
I'm making somewhat like an othello game. I receive a file that contains strings, and i have to read and process them, making the board as it goes.
Example of the file received:
Alejandro,B
Federico,N
B
D6
C4
G5
then i would convert the characters to numbers, so it can fit in the int board[8][8] i use
I was expecting that when it reaches the EOF it would get out of the loop, but instead it never stops the loop and keeps reapeting the last line with the printf.
This is in the main function:
while( EOF != 1 && *error != 1)
{
tomaJugada(&fp,jugada); //takes 1 line of the file
toupper(jugada[0]);
int columna = convierte_a_int(jugada[0])-1; //converts the letter to a number
int fila = (jugada[1]-'0')-1; //converts the char number to int number
printf("columna %i, fila %i \n",columna, fila);
}
This is the auxiliary function:
void tomaJugada(FILE** fp, char jugada[])
{
fgets(jugada,5,*fp);
jugada[2] = '\0';
//jugada[strcspn(jugada, "\n")] = 0;
}
I have seen people using thi:
int ch = getc(fp);
while (ch != EOF){...
but it would consumme data that i need to use, maybe i'm using it wrong?
Resumming: i want to use all the data in the file, reach de EOF, and end the loop. How can i put the condition for the EOF?
I hope i explained myself well, i appreciate any help
EOF in c is just a constant (typically -1), EOF != 1 would always evaluate to the same (that is guaranteed to be true as EOF will always be negative). What you need to do is to check if fgets returns null pointer (that is in the tomaJugada function) and when that happens, then either an error occurred or you've reached the end of the file. To disambiguate between the two you could use the feof function for instance.
An exercise asked to write a function that:
reads a sequence of alphabetic characters (without memorizing the sequence) that ends only when the users enters '\n'.
returns 1 if the number of capitalized letters went beyond the lower ones of at most an integer m, entered by the user, or 0 else.
I tried with the following code:
#include<stdio.h>
int read(int p,char c)
{
int M=0,m=0,d;
char A,Z,a,z;
while(c != '\n')
{
if(A<=c<=Z)
{
M++;
}
else if(a<=c<=z)
{
m++;
}
scanf("%c",&c);
}
if(M-m>0)
d=(m-M);
else
d=0;
if(d==0)
return 0;
else if (d<=p)
return 1;
}
int main()
{
int a,h;
char k;
scanf("%d", &h);
scanf("%c", &k);
a=read(h,k);
printf("%d\n",a);
return 0;
}
At this point, trying to execute the program with the gcc command, i noticed that the program was taking just the integer, let's say 2, and gave back 0 as if it entered in the function without taking the second scan on the character.
Besides the formal misconception and errors about the program and c function that i'm glad you rectify,
I was trying to understand, because as they say i'm trying to be self-taught, how scanf function and function work in general, when and to who priority is given.
For example in function read it's not clear to me when the value i'm returning to the function are taken putting a higher if as i did.
This isn't going to do what you probably expect
if(A<=c<=Z)
... for all sorts of reasons. Firstly, the values of A and Z are uninitialized. Second, the logic is written to be read by a mathematician, not a C compiler.
You almost certainly wanted this:
if('A'<=c && c<='Z')
... and remove the four variables char A,Z,a,z;
Note that use of character constants such as 'A' and 'Z' assumes a runtime environment using ASCII character sets. If you're interested in a more portable solution, you can look up isupper() and islower()
I'm trying to do an assignment for a class where we create a while loop using the scanf function. Basically the program is a calculator where the user should be able to type things like add 20 and my main function should be able to call up the functions from another .c then continue on in the loop.
However this is first time I am programming and I have no idea how to format or begin a loop that scans the input from the user, calls the appropriate mathematical function, applies it, then continues on in the loop.
Here's what I have done for the loop so far, which surprisingly, didn't work:
#include "calc.h"
#include "stdheader.h"
int main(int argc, char ** argv){
int c;
char token[81];
while(c != EOF){
if (scanf("%s", token) == "clear"){
calc.clear();
}else{
}
}
return 0;
}
and here is a sample of the functions that it should be able to call up (or what I have for them at least)
int local;
local = 0;
void clear(void){
local = 0;
printf("\n%d", local);
}
void add(int c){
local = local + c;
printf("\n%d", local);
}
In C, strings (and arrays more generally) are not first-class data types and cannot be compared by ==. Moreover scanf() does not return a string in any case - you should read the documentation carefully.
Change:
if (scanf("%s", token) == "clear")
to:
scanf( "%s", token ) ;
if( strcmp( token, "clear" )
Additionally the test c == EOF is dangerous because c is not initialised.
int c = 0 ;
My observation:
comparing string with == is not a suggested one. Instead try to use strcmp
scanf() returns only integer, you are comparing it to clear in if (scanf("%s", token) == "clear")
changing code like
if(scanf("%5s", token) == 1 && strcmp("clear",token) == 0)
Also what is the initial value of int c = ? without this how can you compare here while(c != EOF)
You need to look at the details of how scanf() works.
Here is a good reference.
scanf() returns the number of tokens read, an int not a string. You can't compare strings with == anyway. To compare strings you would have to use strcmp() from the string.h library.
You don't need to prepend calc on the front of your clear() function.
There are several errors here, you're best path forward might be to try something simpler first.
However this is my first time programming and I have no idea how to format or begin a loop that scans the input from the user, calls the appropriate mathematical function, applies it, then continues on in the loop.
When you want to solve a problem that is more complex than you think that you can solve it break it up in sub-problems. First design the user interface. What should the user enter to communicate with the program.
When you have a plan integrate the features that you need:
parsing user input
formatting of output
number processing (some arithmetic in your example).
A completely different approach to solve your problem.
Have array of function pointers.
typedef int (*func) (int,int);
func a[] = {add,sub,div,mul};
Have your UI like
printf("0 - add , 1- sub, 2 - div, 3 - mul\n");
scanf("%d",&op);
printf("Enter 2 numbers\n");
scanf("%d %d",&var1,&var2);
Now have
a[op](var1,var2);
Define your functions accordingly . For eg
int add(int x,int y)
{
return x+y ;
}
and so on.
I recently recommended K&R to a friend who wanted to learn C. He came across an exercise in the first chapter that gave him various errors. I compiled it on my Ubuntu installation, alternating between the C90 option and the defaults. I've looked at every angle but it seems to be perfect code...yet it consistently gives me a segmentation fault each time I run it. I'm not the sharpest programmer in the shed but this has me pretty frustrated.
What on earth is causing such an error?
Here is the code:
#include <stdio.h>
#define MAXLINE 1000
void reverse(char s[]);
/* A program that reverses its input a line at a time */
main()
{
int c, i;
char line[MAXLINE];
for (i = 0; (c = getchar()) != EOF; ++i) {
line[i] = c;
if (c == '\n') { /* Upon encountering a newline */
line[i] = '\0'; /* replace newline with null terminator */
i = 0;
reverse(line);
printf("\n%s\n", line);
}
}
return 0;
}
/* A function that reverses the character string */
void reverse(char s[])
{
int a, z;
char x;
for (z = 0; s[z]; ++z) /* Figure out where null terminator is */
;
--z;
for (a = 0; a != z; ++a) { /* Reverse array usinng x as placeholder */
x = s[a];
s[a] = s[z];
s[z] = x;
--z;
}
}
You're missing a semi-colon here:
for (z = 0; s[z]; ++z); /* Figure out where null terminator is */
// ^
This loop is supposed to run until it finds the null terminator. If you leave off this semi-colon, then on each iteration it does both ++z and --z, which means it just loops forever. You want the --z to happen after this loop has completed, as that will set z equal to the last character before the string's null terminator.
For an even-length string, a and z will cross each other (they'll never be equal) in the second loop. For example, if z=5 and a=4, then on the next iteration a=5 and z=4. If you check for a<z instead of a!=z then you avoid that problem. Since you're checking for != instead of <, this would cause the loop to run pretty much infinitely. However, you'll end up with a SEGFAULT as a grows too large and z grows too small, since they'll both be used to index into memory outside your buffer.
for (a = 0; a != z; ++a) { /* Reverse array usinng x as placeholder */
// ^ should be <, not !=
Finally, there's also a bug in main. When you find a newline, you set i=0. This works fine when you print the string, but when i is incremented at the end of the loop, you end up with i=1 as you start reading the next string. This means you'll have an extra character at the beginning of your string. You need to do something to properly reset i to make sure that doesn't happen.
K&R has a string reverse function in Section 3.5. In my copy it's on page 62. It looks like your friend decided to iterate over the string rather than calling strlen (which is really all the function call does anyway), and thought that a<z should be equivalent to a!=z.
Does this loop over run?
for (z = 0; s[z]; ++z) /* Figure out where null terminator is */
--z;
for (z = 0; s[z]; ++z) /* Figure out where null terminator is */
--z;
Just after the first iteration, z becomes -1 -- so trying to access s[z] results in segmentation fault.
I have the following in a text file called: values.txt
1 4
2.5 3.76
122 10
277.543
165.4432
I am trying to read the content of this text file, and add each two pairs together and output the result ...
the output would be something like this :
1 Pair:(1, 4) = 5
2 Pair:(2.5, 3.76)= 6.26
and so on ..
I am opening the file like this
int c;
FILE myfile;
myfile= fopen("values.txt", "r");
if ( myfile == NULL ) {
printf("Cannot open TEXT file\n");
return 1;
}
double aa,bb;
while ( (c = getc(myfile) ) != EOF ) {
// HERE SHOULD I DO THE OUTPUT BUT HOW?
}
Any help is really appreciated ..
Language = C
The following code does what you expect. myfile should be declared as FILE*. fopen returns a pointer to FILE structure. If the file is very large, I would recommend reading in buffers of big size (eg: 65535 etc) and parse it char by char and convert it to float values. It reduces system call overhead which takes more time than processing text to float values.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
FILE* myfile;
myfile = fopen("values.txt", "r");
if ( myfile == NULL ) {
printf("Cannot open TEXT file\n");
return 1;
}
double aa,bb;
while (2 == fscanf(myfile, "%lf %lf", &aa, &bb)) {
printf("%lf\n", aa+bb);
}
return 0;
}
For this simple task, use double a, b;
if (fscanf(myfile, "%lf %lf", &a, &b) == 2)
printf("%f + %f = %f\n", a, b, a+b);.
looks like a homework problem but fscanf can read the string into a variable like:
int n;
fscanf (myfile,"%d",&n);
You haven't shown what you need as output for the single-value lines, but this looks like a case for fgets() and sscanf(), unless you really want the two lines with a single value to be processed as a unit.
char buffer[256];
int rownum = 0;
while (fgets(buffer, sizeof(buffer), myfile) != 0)
{
double aa, bb;
int n = sscanf(buffer, "%lf %lf", &aa, &bb);
if (n == 2)
printf("%d Pair:(%g, %g) = %g\n", ++rownum, aa, bb, aa+bb);
else if (n == 1)
printf("%d Solo:(%g) = %g\n", ++rownum, aa, aa);
else
{
printf("Failed to find any numbers in <<%s>>\n", buffer);
}
}
If you used fscanf(myfile, "%g %g", &aa, &bb), then it would read over newlines (they count as white space) looking for numbers, so it would read one number from one line, and the second from another line. This is not usually what people are after (but when it is what you need, it is extremely useful). Error recovery with fscanf() tends to be more fraught than with fgets() and sscanf().
its in c++ sorry :( i dont know c
this is a very simple logic code for simple minde :D im a begineer too, i havent tested this prog so sorry if something goes wrong but exactly
on a same principle was working my parser and it worked fine. so this is a true method. not very efficent but...
do not use this program straight away, understand it's logic this will help you alot. copying that wont give you anything
...parser tutors are so rare....
int x=0;
char ch = 'r'; //i'v used this equasion to avoid error on first ckeck of ch.
it must be filled by something when program starts.
char bigch[10];
int checknumber = 0;
float firstnumber = 0;
float secondnumber = 0;
float result=0;
void clearar(char frombigar[10], int xar) //this function gets bigch as a reference which means that eny
changes made here, will directly affect bigch itself.
ths function gets the actual length of array and puts spaces
in bigch's every element to zero out numbers. we need to clear
bigch of any previous numbers. down below you'l see why i needed this.
'xar' is the x from main function. its here to tell our cleaner the
true length of filled bigar elements.
{
for (int i=0; i
}
}
int main()
{
<------------------- //here you add file opening and reading commands
while(!myfile.eof()) //while end of txt file have not been reached
{
ch=myfile.get(); //gets each letter into ch, and make cursor one step
forward in txt file for further reading.
get() does cursor forwarding automatically
if (ch!= " ") //i used space as an indicator where one number ends
//so while space havent been reahced, read letters.
{ bigch[x] = ch; //get read letter into bigch array.
x++; //icrement bigch array step
}
else
if(ch == " ") //if space is reached that means one number has ended and
{ im trying to set a flag at that moment. it will be used further.
checknumber++; the flag is simple number. first space will set checknumber to 1
second space will set it to 2. thats all.
}
if (checknumber == 1) //if our checknumber is 1, wich means that reading
of first number is done, lets make one whole float
from that bigch array.
{ firstnumber = atof(bigch); //here we get bigch, atof (array to float) command converts
bigch array into one whole float number.
clearar(bigch,x); //here we send bigch and its element step into function where
bigch gets cleaned because we dont want some ghost numbers in it.
abviously clearar function cleans bigch int main function aswell,
not only in it's teritory. its a global cleaning :)
}
else if (checknumber ==2) //here we do the same but if flag is 2 this means that two spaces
had been passed and its time to convert bigch into secondnumber.
{ secondnumber = atof(bigch); //same method of converting array into float (it hates other
not number letters, i mean if its a number its fine. if in your text
was 'a' or 's' in that case atof will panic hehe.. )
clearar(bigch,x); //same thing, we send bigch to cleaner function to kill any numbers
it, we get one space letter ( " " ) into each element of bigch.
}
checknumber = 0; if both two numbers had been read out and converted. we need to reset
space flagger. and start counting form 0; for next pair numbers.
result = firstnumber+secondnumber; well here everything is clear.
}
}