GCC compilation errors related to while statement [duplicate] - c

This question already has an answer here:
Lots of stray errors - "error: stray ‘\210’ in program in C++" [duplicate]
(1 answer)
Closed 8 years ago.
When trying to compile this short C program using GCC I get these errors:
expected ‘)’ before numeric constant
make: *** [file3_5.o] Error 1
stray ‘\210’ in program
stray ‘\227’ in program
stray ‘\342’ in program
Eclipse (Juno) points all of these errors to one line of code:
while(fgets(line ,STRSIZE∗NFIELDS, fp))
Using the following statement to compile:
gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"file3_5.d" -MT"file3_5.d" -o "file3_5.o" "../file3_5.c"
Here is the program I am trying to compile:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRSIZE 100
#define NFIELDS 9
int main()
{
char inputfile[]= "/home/ty/workspace/OpenCoursware_Exercises/Assign_ /stateoutflow0708.txt";
/* define all of the fields */
char state_code_org[STRSIZE];
char country_code_org[STRSIZE];
char state_code_dest[STRSIZE];
char country_code_dest[STRSIZE];
char state_abbrv[STRSIZE];
char state_name[STRSIZE];
char line[STRSIZE*NFIELDS];
int return_num = 0;
int exmpt_num=0;
int aggr_agi= 0;
long total=0;
/* file related */
int fields_read = 0;
FILE* fp=fopen(inputfile,"r");
if(fp==NULL)
{
fprintf(stderr, "Cannot open file\n");
exit(-1);
}
/* skip first line */
fgets(line, STRSIZE*NFIELDS,fp);
/* print the header */
printf ("%-30s,%6s\n","STATE","TOTAL");
printf("---------------------------------------\n");
while(fgets(line ,STRSIZE∗NFIELDS, fp))
{
/* parse the fields */
fields_read=sscanf(line,"%s %s %s %s %s %s %d %d %d",
state_code_org,
country_code_org,
state_code_dest,
country_code_dest,
state_abbrv,
state_name,
&return_num,
&exmpt_num,
&aggr_agi);
if(strcmp(state_code_org, "\"25\"")==0)
{
printf("%-30s, %6d\n", state_name, aggr_agi);
total += aggr_agi;
}
}
/* print the header */
printf(" ----------------------------------------\n");
printf("%-30s,%6lu\n","TOTAL",total);
fclose(fp);
return 0;
}

Your ∗ is not the mulitplication operator * , they may look similar, but are different characters, and gcc doesn't recognize the ∗

while(fgets(line ,STRSIZE∗NFIELDS, fp))
^
^
Should be
while(fgets(line ,STRSIZE*NFIELDS, fp))
^
^
(Whether you see a difference between the two depends on the font used to display the characters).
The ∗ in the first one is not the character used for the multiplication operator, it is this character here.

Your "*" character in STRSIZE*NFIELDS is not the regular * (ascii value 42) but an unicode character "ASTERISK OPERATOR" : http://www.fileformat.info/info/unicode/char/2217/index.htm
That's what the compiler is trying to tell you by complaining about stray characters in the source.

Related

Can not reallocate memory in a very peculiar circumstance

Almost minimal reproducible example:
prog.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *buffer;
int c;
size_t bufsiz = 1024, i = 0;
if (!(buffer = malloc(bufsiz))) {
fputs("malloc() failed!\n", stderr);
return 1;
}
while (EOF != (c = fgetc(stdin))) {
buffer[i] = c;
if (++i == bufsiz && !(buffer = realloc(buffer, bufsiz *= 2))) {
fputs("realloc() failed! (loop)\n", stderr);
return 1;
}
}
buffer[i] = '\0';
if (!(buffer = realloc(buffer, i))) {
fputs("realloc() failed! ", stderr);
fprintf(stderr, "%d\n", i);
return 1;
}
fputs(buffer, stdout);
return 0;
}
I use this command to compile and run:
gcc prog.c -o prog
This command copies the content of prog.c to exp as expected:
cat prog.c | ./prog > exp
This command prints the error message “realloc() failed! 0”:
cat prog.c | ./prog > prog.c
I have yet to find out the reason behind this peculiar behavior...
P.S.: I am using GNU cat and bash
Congratulations, you've (re-)discovered a bug in your system's implementation of realloc, whereby "success" resizing to 0 is indistinguishable from an error. As specified, if realloc returns a null pointer, it has failed and the old object still exists. But some historical implementations treat realloc(p,0) as free(p). Future versions of the C standard allow for this behavior, and deprecate the use of realloc with a zero size, so if you want to use realloc like this you should make sure you are not passing a zero size.
As noted by Eric Postpischil in a comment:
Where does your program put a null character at the end of the string in the buffer?
the fact that 0 is a possible size for your buffer is indicative of a problem - you forgot to reserve space for terminating the string - and if you fix this, even a zero-length string takes a nonzero number of bytes.
In cat prog.c | ./prog > prog.c, the shell parses the command, sees there is a redirection into prog.c, and opens prog.c for writing, which erases any previous contents of the file. Then cat prog.c sees an empty file and copies it to standard output. ./prog faithfully reproduces this empty stream.

gcc -Wformat-truncation warning being raised

gcc 7.1 has introduced a new warning that tells you if you use functions such as snprintf and your arguments would result in output truncation.
The documentation implies that it is only raised if you don't check and act upon the return value:
Level 1 of -Wformat-truncation enabled by -Wformat employs a
conservative approach that warns only about calls to bounded functions
whose return value is unused and that will most likely result in
output truncation.
Here's a sample compilation unit, compiled with version 7.3.0 that illustrates the issue.
#include <stdio.h>
#include <stdlib.h>
int main() {
char w;
int size = snprintf(&w, 1, "%s", "hello world");
if(size<0) {
abort();
}
char *buffer = malloc(size+1);
snprintf(buffer, size+1, "%s", "hello world");
printf("Wrote %d characters: %s\n", size, buffer);
return 0;
}
Compiled like this:
$ gcc -Wformat-truncation=1 test.c
test.c: In function ‘main’:
test.c:8:31: warning: ‘%s’ directive output truncated writing 11 bytes into a region of size 1 [-Wformat-truncation=]
int size = snprintf(&w, 1, "%s", "hello world");
^~ ~~~~~~~~~~~~~
test.c:8:7: note: ‘snprintf’ output 12 bytes into a destination of size 1
int size = snprintf(&w, 1, "%s", "hello world");
Am I misinterpreting the documentation? I can't see how I could check the return value more than I am doing already.
Reference: previous SO question that implies the warning should not be raised. I really don't like disabling warnings and usually compile with -Wall -Werror so I'd appreciate some guidance here.

How to pass system command containing quotes in a C string

Apologies if this has been answered, but I haven't found an answer that solves my problem.
I'm trying to pass a system string in C: the bash version of the command is
grep -w "dog\|animal" myfile
I have the following C code:
char str[50] ="dog\\|animal";
char file[50]="myfile";
char buf[20];
snprintf(buf, sizeof(buf), "grep -w \"%s\" %s",str,file);
system(buf);
When I compile and run it I am given this error:
sh: 1: Syntax error: Unterminated quoted string
Minimum example:
#include <stdio.h>
#include <string.h>
int main(){
char str[50] ="dog\\|animal";
char file[50]="myfile";
char buf[20];
snprintf(buf, sizeof(buf), "grep -w \"%s\" %s",str,file);
system(buf);
}
Transferring comment into answer.
You have two component strings size 50, and you try to squeeze them into a 20-byte target. You should be using perhaps 200 instead of 20.
At any rate, 20 is too short. You have 12 characters of overhead plus 6 in the file name and 11 in the match pattern. That's not going to lead to happiness. (Note that if you had checked the return from snprintf(), it would tell you it needs more space than you gave it.). And the most elementary debug technique would add printf("[%s]\n", buf) to show you what is being executed.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char str[50] = "dog\\|animal";
char file[50] = "myfile";
char buf[20];
int size;
if ((size = snprintf(buf, sizeof(buf), "grep -w \"%s\" %s", str, file)) >= (int)sizeof(buf))
printf("Oops! (%d) ", size);
printf("[%s]\n", buf);
system(buf);
return 0;
}
Example output (program name sh11):
$ ./sh11
Oops! (28) [grep -w "dog\|anima]
sh: -c: line 0: unexpected EOF while looking for matching `"'
sh: -c: line 1: syntax error: unexpected end of file
$
Note that the size returned by sprintf() does not include the null terminator; the buffer needs to be at least 29 bytes to hold everything.

Conflicting types for text to binary converter?

I am trying to create a program that takes a text file and converts it to a binary file. I have created the method to do so, but when I pass it the input and output files, I get a few errors:
unix1% gcc -Wall -Wextra main.c
main.c: In function 'main':
main.c:23:3: warning: implicit declaration of function 'txtbin'
main.c:23:8: warning: assignment makes pointer from integer without a cast
main.c: At top level:
main.c:30:7: error: conflicting types for 'txtbin'
main.c:23:10: note: previous implicit declaration of 'txtbin' was here
main.c: In function 'txtbin':
main.c:40:7: error: incompatible types when assigning to type 'struct FILE *' from type 'FILE'
main.c:41:7: error: incompatible types when assigning to type 'struct FILE *' from type 'FILE'
main.c:54:5: warning: implicit declaration of function 'strlen'
main.c:54:14: warning: incompatible implicit declaration of built-in function 'strlen'
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 255
#define MINLEN 0
#define NUMCHAR 1
#define NUMBYTE 4
int main(int argc, char * argv[]){
FILE* txtf;
FILE* binf;
if(argc != 4){
fprintf(stderr, "Check usage");exit(1);
}
if((txtf =fopen(argv[2], "w+"))==NULL){
fprintf(stderr, "Could not open text file: %s\n", argv[2]);exit(1);
}
if((binf =fopen(argv[3], "w+b"))==NULL){
fprintf(stderr, "could not open binary file: %s\n", argv[3]);
}
binf = txtbin(txtf,binf);
//bintxt();
return 0;
}
FILE* txtbin(FILE in, FILE out){
FILE *ifp;
FILE *ofp;
int tmpint = 0;
unsigned char tmpchr = 0;
char tmpstr[MAXLEN];
ifp = in;
ofp = out;
while(fscanf(ifp, "%s \t %i \n", tmpstr, &tmpint) == 2){
tmpchr = strlen(tmpstr);
fwrite(&tmpchr, sizeof(tmpchr), NUMCHAR, ofp);
fwrite(tmpstr, sizeof(tmpstr[0]), tmpchr, ofp);
fwrite(&tmpint, sizeof(tmpint), NUMBYTE, ofp);
}
fclose(ifp);
fclose(ofp);
return ofp;
}
I know I have a few warnings, but I am most concerned with just getting the program to output the binary file for the respective text file.
By the way, here is the text file:
hello 32
goodbye 56
my 1
name 77
is 91
andrew 3
hello 32
goodbye 56
my 1
name 77
is 91
andrew 3
You need to have a declaration of the function before calling it, add this before main()
FILE* txtbin(FILE in, FILE out);
also, tmpchr should be size_t instead of unsigned char and, this line
fwrite(&tmpint, sizeof(tmpint), NUMBYTE, ofp);
is attempting to write 4 integers, instead of 1, the correct way is
fwrite(&tmpint, sizeof(tmpint), 1, ofp);
And the correct txtbin() signature would be
FILE* txtbin(FILE* in, FILE* out);

C - cs50.h GetString error

Hello I am completely new to the world of programming an I am attempting to take Harvard's CS50 course online.
While making my "Hello World" program, I downloaded 'cs50.h' to define GetString and string (at least I think). So this is the code I wrote:
file.c:
#include "cs50.h"
#include <stdio.h>
int main(int argc, string argv[])
{
string name;
printf("Enter your name: ");
name = GetString();
printf("Hello, %s\n", name);
}
However, whenever I try to make file, this happens:
cc file.c -o file
Undefined symbols for architecture x86_64:
"_GetString", referenced from:
_main in file-JvqYUC.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [file] Error 1
Here is a link to the cs50.h file if it can help: http://dkui3cmikz357.cloudfront.net/library50/c/cs50-library-c-3.0/cs50.h
I would like to know why I get this error and how I can fix it. Please help.
It seems that you forgot to download and link to project cs50.c file from http://dkui3cmikz357.cloudfront.net/library50/c/cs50-library-c-3.0/cs50.c
*.h usually contain only declarations. *.c (for C) and *.cpp (for C++) contains implementations.
There is GetSting function implementation from this class:
string GetString(void)
{
// growable buffer for chars
string buffer = NULL;
// capacity of buffer
unsigned int capacity = 0;
// number of chars actually in buffer
unsigned int n = 0;
// character read or EOF
int c;
// iteratively get chars from standard input
while ((c = fgetc(stdin)) != '\n' && c != EOF)
{
// grow buffer if necessary
if (n + 1 > capacity)
{
// determine new capacity: start at 32 then double
if (capacity == 0)
capacity = 32;
else if (capacity <= (UINT_MAX / 2))
capacity *= 2;
else
{
free(buffer);
return NULL;
}
// extend buffer's capacity
string temp = realloc(buffer, capacity * sizeof(char));
if (temp == NULL)
{
free(buffer);
return NULL;
}
buffer = temp;
}
// append current character to buffer
buffer[n++] = c;
}
// return NULL if user provided no input
if (n == 0 && c == EOF)
return NULL;
// minimize buffer
string minimal = malloc((n + 1) * sizeof(char));
strncpy(minimal, buffer, n);
free(buffer);
// terminate string
minimal[n] = '\0';
// return string
return minimal;
}
Look at your first include statement. You are using " " instead of < >.
In the videos with the CS50 course, the instructor uses carets (< >) rather than quotation marks (" ").
For anyone taking the CS50 class, and don't want to paste the .c code every time, you can also link the CS50 code when compiling.
Place cs50.h and cs50.c in the same directory as file.c, and then type the following in the command line:
clang file.c -lcs50 -o <file name>
The "-l" links the cs50.c and cs50.h files to your c file (after compiling to object file), and "-o" specifies where to put the compiled output.
More information on this here
In your #include"cs50.h" header you should be typing it like this: #include<cs50.h>. Also, try doing:
#include<cs50.h>
#include<stdio.h>
int main(void)
{
string name = get_string("Enter your name: ");
printf("%s\n", name);
}
Instead of this:
#include "cs50.h"
#include <stdio.h>
int main(int argc, string argv[])
{
string name;
printf("Enter your name: ");
name = GetString();
printf("Hello, %s\n", name);
}
That should get rid of the error messages.
P.S
In week 2 they tell you about help50, but if you want you can use it now.
I myself have found it very useful. Here's how it works: in your terminal window(the one where you execute ./hello and clang) you should type : "help50 make hello" (without the quotation marks) and then it will type: asking for help... in yellow. Then it will decipher the error message and type it in a more simple language. For example:
#include <stdio.h>
#include <cs50.h>
int main(void)
{
string name = get_string("Enter your name: ");
printf("%s\n", name)
}
I do make hello, and this appears:
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow hello.c -lcrypt -lcs50 -lm -o hello
hello.c:13:21: error: expected ';' after expression
printf("%s\n", name)
^
;
1 error generated.
<builtin>: recipe for target 'hello' failed
make: *** [hello] Error 1
But when I do it with help50 make hello, this appears:
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow hello.c -lcrypt -lcs50 -lm -o hello
hello.c:13:21: error: expected ';' after expression
printf("%s\n", name)
^
;
1 error generated.
<builtin>: recipe for target 'hello' failed
make: *** [hello] Error 1
Asking for help...
hello.c:13:21: error: expected ';' after expression
printf("%s\n", name)
^
;
Are you missing a semicolon at the end of line 13 of hello.c?
As you can see, now I know my problem and can fix it. Help50 deciphers the error messages into a language you can understand.

Resources