I'm trying to learn some C and have chosen to use the book "SAMS Teach yourself C in 21 days". ( btw is there any good C book at all? This is my third! I always end up with bad or broken code that is supposed to work and hit a wall in my learning process when it doesn't! :-( )
Sadly I've run upon the code underneath that I just should type in and run. The typing went well but the running... well, not so well!
The compiler gives me an error about this line:
{
printf ("Printer busy or disconnected\n"); error_handler; }
when I try to run this code. And since I'm VERY MUCH a novice when it comes to C coding, I have NO IDEA at all what to do, when the editor returns an error messages like this:
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .clean-conf
rm -f -r build/Debug
rm -f dist/Debug/GNU-MacOSX/type_and_run
CLEAN SUCCESSFUL (total time: 158ms)
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
"/usr/bin/make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-MacOSX/type_and_run
mkdir -p build/Debug/GNU-MacOSX
rm -f build/Debug/GNU-MacOSX/Type and run 1.o.d
gcc -c -g -MMD -MP -MF build/Debug/GNU-MacOSX/Type and run 1.o.d -o build/Debug
/GNU-MacOSX/Type\ and\ run\ 1.o Type\ and\ run\ 1.c
i686-apple-darwin10-gcc-4.2.1: and: No such file or directory
i686-apple-darwin10-gcc-4.2.1: run: No such file or directory
i686-apple-darwin10-gcc-4.2.1: 1.o.d: No such file or directory
Type and run 1.c: In function 'do_heading':
Type and run 1.c:54: error: 'error_handler' undeclared (first use in this function)
Type and run 1.c:54: error: (Each undeclared identifier is reported only once
Type and run 1.c:54: error: for each function it appears in.)
make[2]: *** [build/Debug/GNU-MacOSX/Type and run 1.o] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 158ms)
All I can understand is that "error_handler" is undeclared and that it does not seem to be a library function. SIGH!
So said short, is there anything I can do to modify the code so it will work as intended and I can move on?
Or should I just throw the book over in the pile of useless books about C?
Here is the code in its full length:
void do_heading(char *filename);
int line = 0, page = 0;
int main(int argv, char *argc[])
{
char buffer[256];
FILE *fp;
if (argv < 2)
{
fprintf(stderr, "\nProper Usage is: " );
fprintf(stderr, "\n\nprint_it filename.ext\n");
return (1);
}
if ((fp = fopen(argc[1], "r")) == NULL)
{
fprintf(stderr, "Error opening file, %s!", argc[1]);
return (1);
}
page = 0;
line = 1;
do_heading(argc[1]);
while( fgets( buffer, 256, fp ) != NULL )
{
if( line % 55 == 0 )
do_heading(argc[1]);
fprintf( stdout , "%4d:\t%s", line++, buffer );
}
fprintf( stdout , "\f" );
fclose(fp);
return 0;
}
void do_heading(char *filename)
{
page++;
if (page > 1)
fprintf( stdout , "\f");
fprintf( stdout, "Page: %d, %s\n\n", page, filename);
if ((stdout = fopen("PRT:","w")) == NULL) {
printf ("Printer busy or disconnected\n"); error_handler; }
}
Try this book:
C Programming Language (2nd Edition) by Brian W. Kernighan, Dennis M. Ritchie.
You have argv and argc swapped.
if (argv 1)
Should be:
if (argc == 1)
You can simply remove the error_handler chunk as it seems to serve no purpose and is not declared in the code. What the book was likely trying to tell you was to fprintf to stderror perhaps?
So the compiler output might look intimidating, but, as a beginner, the bit you care about is usually in English. This example is no exception:
Type and run 1.c: In function 'do_heading':
Type and run 1.c:54: error: 'error_handler' undeclared (first use in this function)
Type and run 1.c:54: error: (Each undeclared identifier is reported only once
Type and run 1.c:54: error: for each function it appears in.)
It's telling you that error_handler is undeclared. It appears nowhere else in your program so there's no way you're able to use it here. Let's look at the line:
if ((stdout = fopen("PRT:","w")) == NULL) {
printf ("Printer busy or disconnected\n"); error_handler; }
You should know that semicolons are one way to indicate the end of a statement and that good practice is to put just one statement on a line. Break it up:
if ((stdout = fopen("PRT:","w")) == NULL) {
printf ("Printer busy or disconnected\n");
error_handler;
}
Now it's obvious: you're just saying error_handler;; it's not doing anything, it's not a function call (no parentheses), not a variable you're assigning to or reading from so it's clearly a huge fat error. Delete it and try again.
By the way, if the line appeared in the book exactly as you've put it here - with two semicolons on a line - then yes, you should throw it on the fire. Read Kernighan and Ritchie's "The C Programming Language" and do all the exercises in it - you will be amazed how quickly you go from knowing nothing to being ready to work on real programs.
Related
I'm currently trying to use a library previously written by me (matrix.c) within another self-written library (Quaternion.c) by calling it through a header file using the standard method of using a "matrix.h" file with function prototypes from the "matrix.c" file.
"matrix.c" is functional, but when I attempt to compile "Quaternion.c" in MSYS2 MinGW64, using:
gcc -c matrix.c
gcc -c Quaternion.c
gcc matrix.o Quaternion.o -o Quaternion -lgsl
I'm getting this error:
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: Quaternion.o:Quaternion.c:(.text+0x0): multiple definition of `my_handler'; matrix.o:matrix.c:(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
I defined a custom error handler in the GSL "errono.h", and I'm assuming that's the source of the error:
void my_handler (const char * reason, const char * file, int line, int gsl_errno){
if(gsl_errno == 3 || gsl_errno == 7 || gsl_errno == 8 || gsl_errno == 10){
printf("Fatal memory-based error %d, resetting\n", gsl_errno);
exit(0);
//Reset Chip
}
if(gsl_errno == 1 || gsl_errno == 2 || gsl_errno == 4){
printf("User error %d (%s), ignoring calculation and moving forward\n", gsl_errno, reason);
// Return/ignore calculation
}
else
printf("Unexpected error %d, ignoring and moving forward\n", gsl_errno);
// Return/ignore calculation
}
I can't wrap my head around this error because the gsl library is a single source that I've already edited. If somebody could explain why my compilation method (I'm thinking that's what it is) is resulting in the re-definition of that handler, it would be appreciated.
Move the code quote into one of the .c files.
Then only provide the prototype in the .h file.
void my_handler (const char * reason, const char * file, int line, int gsl_errno);
Otherwise the function is defined once for each .c file which gets compiled and does a #include of that header. In your case probably twice.
A reinclusiong guard would not help in this case, because it still happens once per compiled .c file. But having a guard is still a good idea, I assume you have.
Thanks , this has been solved , please see updated code and output in the answer . Thanks Jonathan and everyone else.
I have written below code to read the file present in same directory.
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
int main(){
FILE *fptr;
/*Tried putting different combinations like filename with
quotes|filename without quotes|complete path with quotes|complete path
without quotes*/
if((fptr=fopen("TestFile.txt","r"))==NULL){
printf("\nfopen() returning NULL: %d , %s \n",errno,strerror(errno));
}else{
printf("\nfopen() returning something else: %d , %s
\n",errno,strerror(errno));
}
int c;
while((c=fgetc(fptr))!=EOF){
printf("%c",c);
}}
And i am was getting below output :
./a.out
Segmentation fault (core dumped)
And a GDB core analysis had the following :
(gdb) run
Starting program: /home/astitva/Documents/Coding/a.out
Dwarf Error: wrong version in compilation unit header (is 0, should be 2,
3, or 4) [in module /usr/lib/debug/.build-
id/12/5dab90a4cfa8edc5d532f583e08e810c232cd5.debug]
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
Dwarf Error: wrong version in compilation unit header (is 0, should be 2,
3, or 4) [in module /usr/lib/debug/.build-
id/c0/5201cc642f6b800835e811d7cb28f103aeb191.debug]
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7abc496 in strlen () from /lib/x86_64-linux-gnu/libc.so.6
and my text file TestFile.txt was :
DATA ENETERD AT RUN INSTANCE 1 ------> BLABLABLA
DATA ENETERD AT RUN INSTANCE 2 ------> YADAYADAYADA
DATA ENETERD AT RUN INSTANCE 3 ------> FOOBARFOOBAR
To avoid the warning, you need to #include <string.h> in your code. Add an exit(1) in the error-handling if block :
if((fptr=fopen("TestFile.txt","r"))==NULL){
printf("\nfopen() returning NULL: %d %s\n",errno, strerror(errno));
exit(1);
}
The program needs to exit "gracefully" if the file doesn't exist. So, if there is no valid file present, the program will simply exit and not print anything on the stdout.
EDIT : Just adding on Jonathan's helpful comment on ignoring compiler's warnings :
"If you ignored a compiler warning — don't. If the compiler didn't warn you about the undeclared function strerror(), you need to find the options that make it report such problems (if you use gcc, you would use gcc -Wall -Wextra -Werror — and I'd add -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Wold-style-declaration too, though clang doesn't like -Wold-style-declaration)."
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
EDIT: A complete duplicate of course, isn't the whole point of stackoverflow to ask questions, and get specific answers, the 'answer' you linked me to is:
A. For C++, so partly unintelligible
B. Reads like a wiki article, it is massive, and not specific in the slightest, or in the least bit helpful.
I have copied an example bit of code from the examples folder in the code library (libftdi) I downloaded, to where I want to write my project, when I run it, it has a lot of undefined references, however it runs fine in its original location.
Main file:
#include <stdio.h>
#include <stdlib.h>
#include <ftdi.h>
int main(void)
{
int ret, i;
struct ftdi_context *ftdi;
struct ftdi_device_list *devlist, *curdev;
char manufacturer[128], description[128];
int retval = EXIT_SUCCESS;
if ((ftdi = ftdi_new()) == 0)
{
fprintf(stderr, "ftdi_new failed\n");
return EXIT_FAILURE;
}
if ((ret = ftdi_usb_find_all(ftdi, &devlist, 0, 0)) < 0)
{
fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(ftdi));
retval = EXIT_FAILURE;
goto do_deinit;
}
printf("Number of FTDI devices found: %d\n", ret);
i = 0;
for (curdev = devlist; curdev != NULL; i++)
{
printf("Checking device: %d\n", i);
if ((ret = ftdi_usb_get_strings(ftdi, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0)
{
fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(ftdi));
retval = EXIT_FAILURE;
goto done;
}
printf("Manufacturer: %s, Description: %s\n\n", manufacturer, description);
curdev = curdev->next;
}
done:
ftdi_list_free(&devlist);
do_deinit:
ftdi_free(ftdi);
return retval;
}
Error:
ollieb#ursus ~/Documents/BitBang $ make
make bitbang
make[1]: Entering directory '/home/ollieb/Documents/BitBang'
cc -Wall -g -I/usr/include/libftdi1/ bitbang.c -o bitbang
/tmp/cc20kltT.o: In function `main':
/home/ollieb/Documents/BitBang/bitbang.c:13: undefined reference to `ftdi_new'
/home/ollieb/Documents/BitBang/bitbang.c:19: undefined reference to `ftdi_usb_find_all'
/home/ollieb/Documents/BitBang/bitbang.c:21: undefined reference to `ftdi_get_error_string'
/home/ollieb/Documents/BitBang/bitbang.c:32: undefined reference to `ftdi_usb_get_strings'
/home/ollieb/Documents/BitBang/bitbang.c:34: undefined reference to `ftdi_get_error_string'
/home/ollieb/Documents/BitBang/bitbang.c:42: undefined reference to `ftdi_list_free'
/home/ollieb/Documents/BitBang/bitbang.c:44: undefined reference to `ftdi_free'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'bitbang' failed
make[1]: *** [bitbang] Error 1
make[1]: Leaving directory '/home/ollieb/Documents/BitBang'
Makefile:4: recipe for target 'all' failed
make: *** [all] Error 2
Make file:
CFLAGS=-Wall -g -I/usr/include/libftdi1/
all:
make bitbang
clean:
rm bitbang
You have to link against the ftdi library (-Llibdirectory -llib)
I am working on an assignment for class, in which we have to build a simple shell interface for a Unix system in C. I am using Ubuntu and when I run the source code in that was provided using this command:
osh> cat shell.c
I get an error:
*** omake error: File /home/cameron/cs426/Project1/shell.c: line 11, characters 20-24
unexpected token: string: {
This is my first time using osh, so does anyone have any ideas as to what the issue might be?
Also, here's the code, just in case.
#include<stdio.h>
#include<unistd.h>
#define MAX_LINE 80 /* 80 chars per line, per command */
int main(void)
{
char *args[MAX_LINE/2 + 1]; /* command line (of 80) has max of 40 arguments */
int should_run = 1;
while(should_run){
printf("osh>");
fflush(stdout);
/**
* After reading user input, the steps are:
* (1) fork a child process
* (2) the child process will invoke execvp()
* (3) if command included &, parent will invoke wait()
*/
}
return 0;
}
It looks like this code was intended to be a shell. What you need to do is:
Open a terminal that runs a real shell. osh is the OMake shell, and is probably not relevant this assignment. The code you gave prints "osh", but isn't the osh.
Compile with gcc -o shell-that-calls-itself-osh shell.c The -o flag tells gcc where to put the compiled binary.
Run with ./shell-that-calls-itself-osh The ./ is to run code in the current directory.
I am trying to learn Lex. I have a simple program where i want to read in a file and recognize tokens.
Right now i am getting some errors. I think i am having problems because there is more than one line in the file to recognize the tokens?
Here is the file
fd 3x00
bk
setc 100
int xy3 fd 10 rt 90
here is the output i am trying to achieve:
Keyword: fd
Illegal: 3x00
Keyword: bk
Keyword: setc
Number: 100
Keyword: int
here is my program:
%{
/* Comment */
#include <stdio.h>
#include <stdlib.h>
%}
%%
fd {printf("Keyword: fd\n");}
[0-9][a-z][0-9] {printf("Illegal: 3x00\n");}
bk {printf("Keyword: bk\n");}
setc[0-9] {printf("Keyword: setc\n Number: %s\n", yytext);}
int {printf("Keyword: int\n");}
xy3 {printf("ID: xy3\n");}
fd[0-9] {printf("Keyword: fd\n Number %s\n", yytext);}
rt[0-9] {printf("Keyword: rt \n Number %s\n", yytext);}
%%
main( argc, argv)
int argc;
char** argv;
{
if(argc > 1)
{
FILE *file;
file = fopen(argv[1], "r");
if(!file)
{
fprintf(stderr, "Could not open %s \n", argv[1]);
exit(1);
}
yyin = file;
}
yylex();
}
here are the errors i am getting when i try to compile it:
In function 'yylex':
miniStarLogo.l:11: error: expected expression before '[' token
miniStarLogo.l:11: error: 'a' undeclared (first use in this function)
miniStarLogo.l:11: error: (Each undeclared identifier is reported only once
miniStarLogo.l:11: error: for each function it appears in.)
miniStarLogo.l:11: error: expected ';' before '{' token
miniStarLogo.l:13: error: expected expression before '[' token
miniStarLogo.l:13: error: expected ';' before '{' token
is the error in my printf statements?
Thank you
When I compiled a copy of your code on MacOS X (10.7.2) with flex (2.5.35) and gcc (4.6.1), the only complaints I got from the C compiler were about the non-prototype definition of main(), and that was because I always compile with that warning enabled and mention of yyunput() defined but not used (which is not your fault).
Since you're learning C, you should only be using the notation:
int main(int argc, char **argv)
{
...
}
or an equivalent.
I also converted the miniStarLogo.l file to DOS format (CRLF line endings), and both flex and gcc seemed to be OK with the results - somewhat to my surprise. It might not be the case on your machine.
When I ran the code on your test data, I got:
Keyword: fd
Illegal: 3x00
0
Keyword: bk
setc 100
Keyword: int
ID: xy3
Keyword: fd
10 rt 90
So, you are not far off where you need to be by my reckoning.
Confusion reigneth over my commands.
I used (hmmm, it was GCC 4.2.1 rather than 4.6.1), but:
$ flex miniStarLogo.l
$ gcc -Wall -Wextra -O3 -g -o lex.yy lex.yy.c -lfl
miniStarLogo.l:22: warning: return type defaults to ‘int’
miniStarLogo.l: In function ‘main’:
miniStarLogo.l:42: warning: control reaches end of non-void function
miniStarLogo.l: At top level:
lex.yy.c:1114: warning: ‘yyunput’ defined but not used
$ ./lex.yy <<EOF
> fd 3x00
> bk
> setc 100
> int xy3 fd 10 rt 90
> EOF
Keyword: fd
Illegal: 3x00
0
Keyword: bk
setc 100
Keyword: int
ID: xy3
Keyword: fd
10 rt 90
$
(OK - I cheated marginally: the first time around, I ran rmk lex.yy LDLIBS=-lfl, where rmk is a variant of make and the compilation rules in the directory use the command line shown. But I redid the compilations to get the error messages right, exactly as above.)
You might need to look at expanding your patterns to accept 'one or more' digits with [0-9]+ in place of just [0-9]. You might need to look at a rule dealing with unmatched characters. And personally, I go to great pains to avoid blanks immediately before newlines, so you would need to tighten up your print formatting to meet my criteria. However, that's not germane to getting the program running.
Also, if you need to convert your file from DOS to Unix line endings, the easiest is the dos2unix command, if you have it on your machine. Otherwise, use:
$ tr -d '\015' < miniStarLogo.l > x
$ od -c x
0000000 % { \r \n \r \n / * C o m m e n t
...
0001560 \n } \r \n
0001564
$ mv x miniStarLogo.l
$
I carefully added the carriage returns using vim and :set fileformat=dos; it would also be possible to undo it with vim and :set fileformat=unix. This is Unix so TMTOWTDI (There's More Than One Way To Do It -- the Perl motto), and I'm not even trying to use Perl.