My C program outputs itself - c

Why is my program reading the program itself instead of my text file? What I'm trying to do is read a text file and find out which line of text is the longest, then output that line and how many characters it contains.
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line size */
int getline1(char line[], int maxline);
void copy1(char to[], char from[]);
/* print longest input line */
int main(void)
{
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;
FILE *ptr_file;
ptr_file =fopen("textfile.txt","r");
if (!ptr_file)
return 1;
while (fgets(line,1000, ptr_file)!=NULL)
//printf("%s",line);
//fclose(ptr_file);
//return 0;
while((len = getline1(line, MAXLINE)) > 0)
{
printf("%d: %s", len, line);
if(len > max)
{
max = len;
copy1(longest, line);
}
}
if(max > 0)
{
printf("Longest is %d characters:\n%s", max, longest);
}
printf("\n");
return 0;
} //end main
/* getline: read a line into s, return length */
int getline1(char s[], int lim)
{
int c, i, j;
for(i = 0, j = 0; (c = getchar())!=EOF && c != '\n'; ++i)
{
if(i < lim - 1)
{
s[j++] = c;
}
}
if(c == '\n')
{
if(i <= lim - 1)
{
s[j++] = c;
}
++i;
}
s[j] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume 'to' is big enough */
void copy1(char to[], char from[])
{
int i;
i = 0;
while((to[i] = from[i]) != '\0')
{
++i;
}
}

The while loop in you main should look like (don't need the inner loop in which inside getline1() getchar() reads from stdin):
while (fgets(line, 1000, ptr_file)!=NULL) {
len = strlen(line);
if (len > max) {
max = len;
strncpy(longest, line, 1000);
}

Related

Trying to make QuizMaker in C, but some steps are ignored with !X

Basically I'm trying to make QuizMaker by asking user how many questions they want, then make a string of an array. I'm new to C, so I might be missing some little details. Please look at the screenshot of console which I included.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 4096
int input(char *str, int n);
int main() {
int a, i, length = 0;
printf("How many questions do you want?\n");
scanf("%d", &a);
char *strarr[a];
char buffer[BUFFER_SIZE]; //string holder
while (getchar() != '\n'); //in case there is \n, flush it
for(i = 0; i < a; i++) {
printf("Question number #%d:\n", i + 1);
length = input(buffer, BUFFER_SIZE);
//input method returns number of chars we've entered
strarr[i] = malloc((length) * sizeof(char));
//allocating memory for each pointers to array of chars
strcpy(strarr[i], buffer);
//copy the string you've just created to an array of strings
}
//printing results
printf("_____________\n");
for(i = 0; i < a; i++) {
printf("%s\n", strarr[i]);
}
return 0;
}
int input(char *str, int n) {
int ch, i = 0;
while ((ch = getchar()) != '\n') {
if (i < n)
str[i++] = ch;
str[i] = '\0';
}
return i;
}
There are some problems in the code:
the test if (i < n) is not strict enough: you should stop storing characters to the destination array before it is full to save space for the null terminator.
you must allocate one extra byte for the null terminator: malloc((length + 1) * sizeof(char)) or just malloc(length + 1) as sizeof(char) is 1 by definition.
you should test for EOF in addition to '\n' in the reading loops.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 4096
int input(char *str, int n);
int main() {
int a, c, i, length = 0;
printf("How many questions do you want?\n");
if (scanf("%d", &a) != 1 || a <= 0) {
fprintf(stderr, "invalid input\n");
return 1;
}
char *strarr[a];
char buffer[BUFFER_SIZE]; //string holder
// flush the rest of the input line
while ((c = getchar()) != EOF && c != '\n')
continue;
for (i = 0; i < a; i++) {
printf("Question number #%d:\n", i + 1);
//input method returns number of chars we've entered
length = input(buffer, BUFFER_SIZE);
//allocating memory for each pointers to array of chars
strarr[i] = malloc((length + 1) * sizeof(char));
if (strarr[i] == NULL) {
fprintf(stderr, "allocation error\n");
a = i;
break;
}
//copy the string you've just created to an array of strings
strcpy(strarr[i], buffer);
}
//printing results
printf("_____________\n");
for (i = 0; i < a; i++) {
printf("%s\n", strarr[i]);
}
return 0;
}
int input(char *str, int n) {
int ch, i = 0;
while ((ch = getchar()) != EOF && ch != '\n') {
if (i + 1 < n)
str[i++] = ch;
}
if (i < n)
str[i] = '\0';
return i;
}
Also note that you can use strdup() to allocate and copy the string in a single call:
for (i = 0; i < a; i++) {
printf("Question number #%d:\n", i + 1);
input(buffer, BUFFER_SIZE);
/* allocate a copy of the string */
strarr[i] = strdup(buffer);
if (strarr[i] == NULL) {
fprintf(stderr, "allocation error\n");
a = i;
break;
}
}

Conflicting types for 'function'

I'm learning C with "The C programming language" book. And I'm stucked with this error.
Here is the code:
#include <stdio.h>
#define MAXLINE 1000 // Max input line length
int getline(char line[], int maxline);
void copy(char to[], char from[]);
// Printing the longest input line
int main()
{
int len; // Current line length, max line length ever seen
int max;
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while((len = getline(line, MAXLINE)) > 0)
{
if(len > max) // If current line length > previous max length - rewrite.
{
max = len;
copy(longest, line);
}
}
if(max > 0) // If there was a line
printf("%s", longest);
return 0;
}
int getline(char s[],int lim) // return length of line
{
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;
}
This code is an example from the book :)
Trying to compile it on Linux: Linux 5.4.97-gentoo.
GCC version: 10.2.0.
getline is already declared in <stdio.h>. Change the method name to my_getline.

Length of line in function defaults to 1 after first user input, why?

I am practicing an algorithm from the C programming book and want to output the length of each line after it is typed. After I write a sentence, it gives me the correct out put of "This is a line of length 10" or something. Then in keeps repeating "This is a line of length 1" over and over until I control +z. How can I get it to just print the length and then continue to receive input each time?
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line size */
int getlines(char line[], int maxline);
void copy(char to[], char from[]);
/* 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 = getlines(line, MAXLINE)) > 0)
printf("This is the line length %d.", len);
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* getline: read a line into s, return length */
int getlines(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++;
}
Thank you.
You forgot to enclose statements of the while loop in braces and you need to change the condition of the loop.
while ((len = getlines(line, MAXLINE)) > 1 )
{
printf("This is the line length %d.", len);
if (len > max) {
max = len;
copy(longest, line);
}
}
Or the condition in the while loop can look like
while ((len = getlines(line, MAXLINE)) != 0 && line[0] != '\n' )
Pay attention to that the second parameter of the function copy should have the qualifier const
void copy(char to[], const char from[]);
I ran it and its ok. However you need to note that you were using max which is a keyword and hence your code will not work. see here for more information on max
I modified it a little to help you see better:
int main()
{
int len; /* current line length */
int maxVal; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
//char longest[MAXLINE]; /*longest line saved here */
maxVal = 0;
printf("Enter Input: ");
while ((len = getlines(line, MAXLINE)) > 0){
printf("This is the line length %d.\n", len);
if (len > maxVal) {
maxVal = len;
//copy(longest, line);
printf("Longest Line is now: %s", line);
}
printf("Enter Input: ");
}
return 0;
}
You can use this if there is no other need for longestLine since all you wanted was to print it based on your code
The output was as follow when tested:
Enter Input: Hello
This is the line length 6.
Longest Line is now: Hello
Enter Input: World
This is the line length 6.
Enter Input: Worldly Affairs
This is the line length 16.
Longest Line is now: Worldly Affairs
Enter Input: Hello World
This is the line length 12.
Enter Input:

Problem in Example 1.9 - The C Programming Language

I have tried to compile and run the program below which is the example 1.9 of the book The C Programming Language. It is compiled OK and no errors are found. However, when I run it and see if the program works, instead of returning me the longest line, it returns a sequence of garbage characters with the same length of the longest line.
Here is the program:
#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;
++i;
}
s[i] = '\0';
return i;
}
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i] != '\0')) {
++i;
}
}
This expression:
(to[i] = from[i] != '\0')
is not doing what you think. It will compare from[i] != '\0' first, and assign the result to to[i]. This means the destination string will be the correct length but full of characters with code 1.
So probably you copied the parenthesis in the wrong position:
(to[i] = from[i]) != '\0'

What exactly breaks the while loop in main?

What exactly breaks the while loop in this code? This is code from the book The C Programming Language from the C creators. It is a code from section 1.9. I guess int len will always be bigger than 0, but somehow when I compile this code the while loop breaks when I press Ctrl+Z (which is EOF for Windows).
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */
int mgetline(char line[], int maxline);
void copy(char to[], char from[]);
/* print the 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 = mgetline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
if (max == len)
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* mgetline: read a line into s, return length */
int mgetline(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;
}
Loop 1: (In copy)
Strings in C are NUL-terminated by convention. NUL is a special char value with the value 0.
The value of the expression to[i] = from[i] is the new value of to[i].
That is 0 when NUL is reached, and the loop exits.
Loop 2: (In main)
Similarly the value of len = mgetline(line, MAXLINE) is the new value of len. That is 0 if mgetline returns 0 which is does when no characters are read. So that loop exits.

Resources