Old C code not compiling - c

I am trying this old example from "The C Programming Language". I am getting a conflicting types error with the getline function. I also tried placing the function before main. I am using gcc 4.6.3 as my compiler.
#include <stdio.h>
#define MAXLINE 1000
int getline(char line[], int maxline);
void copy(char to[], char from[]);
int main(void)
{
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max=0;
while((len= getline(line, MAXLINE))>0)
if(len>max){
max=len;
copy(longest,line);
}
if (max>0)
printf("%s", longest);
return 0;
}
int getline(char s[], int lim)
{
int c,i;
for(i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i]=c;
if(c=='\n'){
s[i]=c;
++i;
}
s[i]='\0';
return i;
}
void copy(char to[], char from[])
{
int i;
i=0;
while((to[i]=from[i])!= '\0')
++i;
}

getline is a standard POSIX function nowadays, with a different signature than the function in this K&R example. Rename getline to something else and it should work.
Alternatively, compile with gcc -std=c89 (or -std=c99) to get pure ISO C mode without POSIX or GNU extensions.

Your getline function is clashing with getline as provided by the standard library. It'd be best to rename your function.

Related

gcc errors "conflicting types for" and "previous declaration of" during compiling

I am getting these errors despite declaring the "getline" and "copy" function prototypes before main(). This program comes straight from the code in The C Programming Language so I'm unsure what the issue is and how to fix it.
#include <stdio.h>
int getline(char line[], int maxline);
void copy(char to[], char from[]);
int main()
{
}
int getline(char s[], int lim)
{
int c, i;
for (i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
The exact errors produced by the compiler are:
string_reverser.c:4:5: error: conflicting types for 'getline'
int getline(char line[], int maxline);
^~~~~~~
In file included from string_reverser.c:1:0:
c:\mingw\include\stdio.h:650:1: note: previous declaration of 'getline' was here
getline (char ** __restrict__, size_t * __restrict__, FILE * __restrict__);
^~~~~~~
string_reverser.c:27:5: error: conflicting types for 'getline'
int getline(char s[], int lim)
^~~~~~~
In file included from string_reverser.c:1:0:
c:\mingw\include\stdio.h:650:1: note: previous declaration of 'getline' was here
getline (char ** __restrict__, size_t * __restrict__, FILE * __restrict__);
^~~~~~~
The POSIX function getline() is now a standard library function which is (already) declared in <stdio.h> (but wasn't standard when K&R was written).
Hence, you cannot re-declare the function a little differently in C language.
A workaround is to rename your getline function to something else, e.g. getline_new
The updated code is as below with this workaround, or you may want to switch to C++ that gives flexibility to have many functions with same name, but different arguments, including argument type (polymorphism concept)
#include <stdio.h>
int getline_new(char line[], int maxline);
void copy(char to[], char from[]);
int main()
{
}
int getline_new(char s[], int lim)
{
int c, i;
for (i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}

C compiler expecting additional argument in function despite not being declared

I am declaring a function with 2 arguments and calling it with 2 arguments however the compiler seems to be converting it into a function that requires an additional argument of type FILE * __restrict.
I'm on Mac OSX 10.11.6
using both cc and gcc produces the same error.
What argument should I be giving the function or should I be changing a setting with my compiler? Or have I just missed a typo somewhere...
Errors are:
longest-line.c:6:5: error: conflicting types for 'getline'
int getline(char line[], int maxline);
^
/usr/include/stdio.h:442:9: note: previous declaration is here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
longest-line.c:17:37: error: too few arguments to function call, expected 3, have 2
while ((len = getline(line, MAXLINE)) > 0)
~~~~~~~ ^
/usr/include/stdio.h:442:1: note: 'getline' declared here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
longest-line.c:28:5: error: conflicting types for 'getline'
int getline(char s[], int lim)
^
/usr/include/stdio.h:442:9: note: previous declaration is here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
3 errors generated.
Code is:
#include <stdio.h>
#define MAXLINE 1000
int getline(char line[], int maxline);
void copy(char to[], char from[]);
int main()
{
int len; /* current line length */
int max; /* maximum length so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
int getline(char s[], int lim)
{
int c, i;
for (i = 0; i<lim-1 && (c=getchar()) != 'X' && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
i++;
}
s[i] = '\0';
return i;
}
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
getline is a name reserved (in POSIX), you can't use it without trouble, change your function name.
getline is defined in stdio.h. When you're declaring it, another declaration has already been provided and your version isn't being picked up.
As Stargateur has already pointed out, it's reserved -- change your function name.

K&R Error: conflicting method definition

I am going through K&R (2 ed.) to learn C as I've been trying to get a basis in lower-level languages to help my programming and also because I want to know C. The book is absolutely fantastic; however, a program they provided on pp. 29 (Sec 1.9 Character Arrays) does not compile. This is the code
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line size */
int getline(char line[], int maxline);
void copy(char to[], char from[]);
/* print longest input line */
main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* getline: read a line int s, return length */
int getline(char s[], int lim)
{
int c, i;
for (i = 0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
When I run cc longest_line.c (that's what I called it) I get an error that getline has conflicting definitions as it was already defined in stdio.h. My question is, how do I resolve this/can I resolve this without giving getline a different name?
As #Olaf commented, getline() is standard POSIX,
K&R second edition is ansi 89 standard.
Just compile in ansi mode, to prevent the collision with POSIX libraries:
gcc -ansi source.c
Edit:
GodBot Link
This approach avoids your problem by not including the problematic header. Rather, it copies all the declarations needed in your implementation locally.
This is a very bad idea because the declarations of these functions may change without your knowledge in which case your code will pass or receive bad inputs
#define MAXLINE 1000 /* maximum input line size */
int getline(char line[], int maxline);
void copy(char to[], char from[]);
int printf(const char *format, ...);
int getchar(void);
/* print longest input line */
int main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* getline: read a line int s, return length */
int getline(char s[], int lim)
{
int c, i;
for (i = 0; i<lim-1 && (c=getchar())!=-1 && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
~

Encapsulation in C functions - K&R section 1.9

I am fairly new to C, and I am working through Ritchie's and Kernighan's The C programming language, and I don't understand how the following code works:
#include <stdio.h>
#define MAXLINE 1000
int getline(char line[], int maxline);
void copy(char to[], char from[]);
int main()
{
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0)
printf("%s", longest);
return(0);
}
int getline(char s[], int lim)
{
int c, i;
for (i=0; i<lim-1 && (c = getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
}
s[i] = '\0';
return(i);
}
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
What I don't get is how does the copy function affect anything without returning anything, I am used to Python where functions can only affect outwith themselves through return values, and I was under the impression C was the same.
I have tested the code and it does work.
The statement while ((to[i] = from[i]) != '\0') is actually an assignment disguised within the comparison.
It's a shorthand code that I personally find confusing, and you're proving that it infact is.
That copy function works through the magic of pointers.
In essence, pointers are basically a memory address that you can access like an array from the same program.
On a side note, Learn C the Hard way is, in my opinion, a better book.
He explains many concepts of C, and he also points out some flaws in that very same copy function you are asking about.
UPDATE
He actually removed his section on K&R C, because he believes that C is dead.
I think he is wrong, but, to each his own.
void copy(char to[], char from[]) is actually the same like void copy(char *to, char *from). So, two pointers are passed to the copy function. The function can change the destinations of the pointers. This mechanism is known as "call by reference".
(The copy function only needs to change the destination of the to-pointer, the destination of the from-pointer needs not to be changed. This can be made clearer with void copy(char *to, const char *from).)

getline not declared in this scope despite importing stdio

I need to use getline() in C, but when i write:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
char *line;
getline(&line, NULL, stdin);
free(line);
return (0);
}
compiler writes error: getline was not declared in this scope what can i do? Isn't getline is delared in stdio.h? I never had this kind of problem before.
I use GCC GNU Compiler.
You need to define _GNU_SOURCE to use this function, either define it before the inclusion of stdio.h or pass it to the compile as -D_GNU_SOURCE since this is a GNU extension function.
Another possible cause is that your GLIBC does not have this function, so either try:
grepping for it in /usr/include/stdio.h
Test for _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700 like the manual page says (after including features.h)
The following implementation may work (Un-tested):
#define INTIAIL_SIZE 100
size_t getline(char **lineptr, size_t *n, FILE *stream)
{
char c;
size_t read = 0;
char *tmp;
if (!*lineptr) {
if (!n)
*n = INTIAIL_SIZE;
tmp = malloc(*n);
*lineptr = tmp;
} else
tmp = *lineptr;
while ((c = fgetc(stream)) != '\n') {
*tmp++ = c;
if (++read >= *n) {
char *r = realloc(tmp, *n * 2);
if (!r) {
errno = ENOMEM;
return -1;
} else
tmp = r;
}
}
*n = read;
return read;
}
Errors you currently have:
You're not freeing line after you've used it
You're not passing line by reference, since the function prototype is: ssize_t getline(char **lineptr, size_t *n, FILE *stream); hence char **lineptr

Resources