I am learning to use getline in C programming and tried the codes from http://crasseux.com/books/ctutorial/getline.html
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int atgc, char *argv[])
{
int bytes_read = 1;
int nbytes = 10;
char *my_string;
my_string = (char *)malloc(nbytes+1);
puts("Please enter a line of text");
bytes_read = getline(&my_string, &nbytes, stdin);
if (bytes_read == -1)
{
puts ("ERROR!");
}
else
{
puts ("You typed:");
puts (my_string);
}
return 0;
}
However, the problem is that the compiler keeps returning errors of this: undefined reference to 'getline'.
Could you please tell me what the problem is? Thank you!
I am using Win7 64bit + Eclipse Indigo + MinGW
The other answers have covered most of this, but there are several problems. First, getline() is not in the C standard library, but is a POSIX 2008 extension. Normally, it will be available with a POSIX-compatible compiler, as the macros _POSIX_C_SOURCE will be defined with the appropriate values. You possibly have an older compiler from before getline() was standardized, in which case this is a GNU extension, and you must #define _GNU_SOURCE before #include <stdio.h> to enable it, and must be using a GNU-compatible compiler, such as gcc.
Additionally, nbytes should have type size_t, not int. On my system, at least, these are of different size, with size_t being longer, and using an int* instead of a size_t* can have grave consequences (and also doesn't compile with default gcc settings). See the getline manual page (http://linux.die.net/man/3/getline) for details.
With that change made, your program compiles and runs fine on my system.
I am also using MinGW. I checked MinGW headers and getline() does not appear in any C header, it appears only in C++ headers. This means the C function getline() does not exist in MinGW.
getline isn't a standard function, you need to set a feature test macro to use it, according to my man page,
_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
for glibc 2.10 or later,
_GNU_SOURCE
before that.
Related
I want to print the content of a txt file (first parameter), but the function to do so is in a different file.
I have the following main file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fileoperation.h"
int main(int argc, char **argv)
{
read(argv[1]);
return 0;
}
and then in the fileoperation.c file I have:
#include "fileoperation.h"
void read(char* file)
{
FILE *fptr;
char c;
fptr = fopen(file, "r");
if (fptr == NULL)
{
printf("Cannot open file \n");
exit(0);
}
c = fgetc(fptr);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(fptr);
}
fclose(fptr);
}
If I type the code from the function in the main function, it works. I don't understand why is not working
The header file of fileoperation.c is
#ifndef FILEOPERATION_H
#define FILEOPERATION_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void read(char* file);
#endif
Rename your function. read exists in the backing libraries. To make matters worse, the compiler knows what it does and optimizes it out.
Could have been worse. You could have replaced the actual read with your own and blown up the standard libraries.
You appear to be using a non-standard compiler, or you have configured it incorrectly. Compilers like gcc and clang are known to invoke non-compliant behavior unless you compile with -std=c17 -pedantic-errors (see What compiler options are recommended for beginners learning C?). I cannot reproduce the problem using a C compliant compiler.
A compliant compiler is not allowed to place non-standard identifiers in standard headers other than those explicitly reserved by the C standard. Examples of reserved identifiers are those with two leading underscores, those with a leading underscore followed by an upper-case letter and identifiers reserved for future language/library extensions. Source: ISO 9899:2018 chapters 4/6, 7.1.3, 6.11 and 7.31.
The mentioned compilers should remove all non-standard identifier declarations when compiling in C language compliant mode as described above. If it doesn't, you have found a compiler library bug.
There exists an old, well-known (and incredibly poorly named) function read, but it has never been part of the standard C library. (POSIX tried to standardize it but that's irrelevant here.) So the easy solution is to simply not name an identifier read - not so much because a well-known non-standard function has that name, but because it is a very poor and non-descriptive identifier name. In your case you could have used read_file or similar.
The C standard library includes a method, strerror_r (https://linux.die.net/man/3/strerror_r).
Depending on the "feature test macros" defined at compilation time, and compiling vs the GNU standard headers, one of two definitions gets included:
int strerror_r(int errnum, char buf, size_t buflen);
/ XSI-compliant */
char *strerror_r(int errnum, char buf, size_t buflen);
/ GNU-specific */
The XSI-compliant version of strerror_r() is provided if:
(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
Otherwise, the GNU-specific version is provided.
Assuming I'm dynamically linking my application vs. the standard library, how does the linker correctly link vs. the proper definition of the function?
One of them is actually called __xpg_strerror_r and is redirected to be used as strerror_r if needed, see:
https://code.woboq.org/userspace/glibc/string/string.h.html#409
I have a version of a program that used to compile to a *.o file, but now it does not, and gives a compiler error.
I have tried to compile my code with gcc compiler on Linux, and the compile fails.
#include <stdio.h>
int isatty();
long isatty_(lio_number)
long *lio_number;
{
int file_desc;
if ((*lio_number)==5)
{
file_desc = stdin->_file;
return isatty(file_desc);
}
else
return 0;
}
I expect the command gcc -c isatty.c to yield isatty.o but it does not. Instead, I get this message:
isatty.c: In function ‘isatty_’:
isatty.c:11: error: ‘struct _IO_FILE’ has no member named ‘_file’
Never use any members of the FILE structure.
Use fileno(stdin) instead of stdin->_file.
The member _file is a MinGW-specific name for the file descriptor, while fileno is a widely-supported POSIX-compliant function.
Along with that, you may want to #include <unistd.h> instead of defining isatty explicitly.
If you're limited to writing your code this way for some reason, don't expect it to be portable. Otherwise, this should work:
#include <stdio.h>
#include <unistd.h>
long isatty_(long *lio_number)
{
int file_desc;
if (*lio_number == 5)
{
file_desc = fileno(stdin);
return isatty(file_desc);
}
else
{
return 0;
}
}
What this changes is that it includes unistd.h which provides a declaration for isatty, it includes the types of the arguments within the function definition, and it uses fileno(stdin) instead of stdin->_file, of which the former is much more portable. It also improves the formatting so others can read your code if they need to.
Modernize the code. The original seems to be targeting some ancient Unix. This should work on more recent POSIX-compliant systems, since virtually every such system should provide the fileno() function. Changing the code to standard C is also a good idea.
So use fileno(), include <unistd.h> instead of forward declaring isatty(), and use standard C function parameter declarations:
#include <stdio.h>
#include <unistd.h>
long isatty_(long *lio_number)
{
if (*lio_number == 5)
{
return isatty(fileno(stdin));
}
return 0;
}
I'm trying to port some code from windows to linux, but I'm having difficulty with support for large files. off_t seems to be defined when gcc is run with -std=c89 but not for -std=c99. Even a trivial test case will not compile:
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
int main()
{
off_t x = 0;
return 0;
}
It really doesn't seem like this should be difficult (in fact, it's not on all other operating systems). Anyone have any idea what is happening?
The type off_t is not defined by ISO C; it's defined by POSIX.
I get
error: unknown type name ‘off_t’
if I compile with either -std=c90, -std=c99, or -std=c11. That's to be expected, since those options specify conformance to the relevant C standard. Since you're compiling C code that doesn't conform to any of those C standards, you shouldn't use those options.
I find that off_t is defined if I compile with -std=gnu90, -std=gnu99, or -std=gnu11.
Also, off_t is the return type of the lseek function, whose man page on my system says it requires:
#include <sys/types.h>
#include <unistd.h>
You should add those.
I'm trying to write a portable function in c that compares the last modified times of 2 files. The files are tiny and written one right after the other, so I need finer granularity than 1 second (milliseconds).
There seems to be a plethora of time/date functions...
You should look to the stat() function. It's available on *nix and on windows.
They will both return you a struct containing a field name st_msize. They are the finest functions I have heard of in order to get this kind of information from an Operating System.
Since you need portability, beware to take care of the various different types available on Windows. On *NIX, it's a classic time_t structure. If you include specific call, you can obtain nano seconds mtime: it was defined in POSIX.1-2008, according to the man page.
You can also take a look at how you can deal with 64/32 bit time_t
The C standard does not have any functions for this, but the Posix specification does. The 2008 edition even provides sub-second timestamps. #define _POSIX_C_SOURCE 200809L
The following code should give you an idea how to use it.
#define _POSIX_C_SOURCE 200809L
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h> // for printf
#include <stdlib.h> // for EXIT_FAILURE
int main(int argc, char **argv)
{
for (int i = 1; i < argc; ++i) {
struct stat st = {0};
int ret = lstat(argv[i], &st);
if (ret == -1) {
perror("lstat");
return EXIT_FAILURE;
}
printf("%s: mtime sec=%lld nsec=%lld\n", argv[i],
(long long) st.st_mtim.tv_sec,
(long long) st.st_mtim.tv_nsec);
}
return 0;
}
For POSIX UNIX, stat() is portable and gives struct stat st_mtime which is the modification time in epoch seconds. Windows stat returns windows time values, and has creation time rather than st_ctime.
For non-POSIX UNIX implementations, Windows and other OSes there is no portable concept of file modification time. So, depending on your idea of portable, this whole concept may or my not work for you.