File IO: Line by Line Comparison In C, Segmentation Fault - c

I'm really stuck on this problem. I'm trying to write a program in C that will take a file, and check to see if every line is in alphabetical order.
So the text file
apple
banana
grape
grape
orange
The program would print to stdout "Lines are in order". If the lines are out of order it would print say the lines are out of order and print the first pair of lines where that occurs.
The main thing I'm having trouble with is just debugging, I keep getting a segmentation fault and I'm not sure why. I don't think that theres an instance where I'm trying to dereference a null pointer and I don't think there's an instance where I try to assign something with more memory than a pointer can handle so I'm not sure what the issue is.
Below is my code, I'm really new to C so if there is anything obvious or fundamental flaws in my code I'd really appreciate being told so.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(char* argv[],int argc){
char* fileN = argv[1];
FILE* file = fopen(fileN,"r");
if (file == NULL){
perror("Error: Couldn't open file");
exit(1);
}else{
char *line = malloc(101*sizeof(char));
fgets(line,101,file);
char *comp = malloc(101*sizeof(char));
while(line){
fgets(comp,101,file);
if (comp){
if(strcmp(line,comp) > 0){
printf("Lines out of order\n");
printf("%s\n",line);
printf("%s\n",comp);
free(line);
free(comp);
fclose(file);
exit(1);
}
}
line = comp;
}
printf("Lines are ordered\n");
free(line);
free(comp);
fclose(file);
exit(0);
}
}

Thanks for the help everyone, here is a version of the program that works.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc,char* argv[]){
char* fileN = argv[1];
FILE* file = fopen(fileN,"r");
if (file == NULL){
perror("Error: Couldn't open file");
exit(1);
}else{
char line[101], comp[101];
fgets(line,101,file);
int bool = 1;
while(line && bool){
if (fgets(comp,101,file) != NULL){
if(strcmp(line,comp) > 0){
printf("Lines out of order\n");
printf("%s",line);
printf("%s\n",comp);
fclose(file);
exit(1);
}
strncpy(line,comp,100);
}else{
bool = 0;
}
}
printf("Lines are ordered\n");
fclose(file);
exit(0);
}
}
My mistakes were A) forgetting how to properly copy one string over to one another and B) not realizing that fgets would return null if it fails, that's what I needed to use to make sure my loops actually ends.

Tell me, if you need comments.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE 100
int main(int argc, char* argv[]) {
char a[MAX_LINE];
char b[MAX_LINE];
FILE* fd = fopen(argv[1], "r");
if(!fd) {
puts("Error: Couldn't open file");
exit(1);
}
fgets(a, MAX_LINE, fd);
while(fgets(b, MAX_LINE, fd)) {
if(strcmp(a, b) > 0) {
puts("Lines out of order");
printf("a = %s", a);
printf("b = %s", b);
fclose(fd);
exit(1);
}
strcpy(a, b);
}
puts("Lines are ordered");
fclose(fd);
return 0;
}

Related

Why the hyphen(-) is not printed?

#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{
FILE* fp = fopen(argv[1],"r");
char* ptr;
int size;
while(1){
int scanfinteger = fscanf(fp,"%d",&size);
ptr = (char*)malloc((size+1)*sizeof(char));
if(scanfinteger != 1){
int result = fscanf(fp,"%s",ptr);
printf("ptr:[%s]\n",ptr);
if(result == EOF)
break;
}
}
return 0;
}
input_file(argv[1]) contains this
10 This
10 is
10 buffers
10 -
10 hi
10 -hello
my program's output
ptr: [This]
ptr: [is]
ptr: [buffers]
ptr: [10]
ptr: [hi]
ptr: [hello]
I can't understand why the hyphen gets consumed. Has someone had seen this issue?
Thank you!
If I may suggest a different solution, I would suggest you read lines and then parse the lines.
Perhaps something like this:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char* argv[])
{
// First make sure you have enough arguments
if (argc < 2)
{
printf("Need an argument!\n");
return 1;
}
// Open the file, and make sure we succeeded
FILE *fp = fopen(argv[1], "r");
if (fp == NULL)
{
printf("Failed to open the file %s: %s\n", argv[1], strerror(errno));
return 1;
}
// Now read the file, one line at a time
char line[100];
while (fgets(line, sizeof line, fp) != NULL)
{
// Now we have a line, attempt to parse it
int value;
char string[100];
if (sscanf(line, "%d %99s", &value, string) != 2)
{
printf("Failed to parse the current line\n");
break; // Break out of the loop
}
printf("Read value %d, string '%s'\n", value, string);
}
// All done, or we had an error (should probably check that)
// Anyway, close the file and end the program
fclose(fp);
}
The problem with your current code (which doesn't seem to be the actual code you run) is that you only read the string if the reading of the number fails.
What the problem is with your actual code, that produces that output, I don't know. But somehow it comes out of sync. This can be seen in that you for one line read the number as the string.

File pointers led to core dump. Probably something stupid

Write the program myuniq.c that contains a function void process_file(FILE* f) that reads all input from the given file one line at the time while keeping two consecutive lines in memory, and prints each line to the standard output if it is not equal to the previously read line.
^^This is the assignment i'm working on. My code below is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void process_file(FILE* f);
int main()
{
FILE *fil = fopen("text.txt","r");
process_file(fil);
return 0;
}
void process_file(FILE* f)
{
FILE *fi = f;
char *firstLine = fgets(firstLine, 999, f);
char *secondLine = fgets(secondLine, 999, f);
while (feof(fi))
{
if (firstLine == secondLine)
{
puts(secondLine);
}
else
{
puts(firstLine);
puts(secondLine);
}
firstLine++;
secondLine++;
}
}
It compiled fine...but on every run it says core dumped. I can't see where I went wrong? Any ideas?
You don't check the return value of fopen, you don't allocate any memory for the strings into which you read, you don't continue reading input from the file, you don't correctly check for the end of input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MY_MAX_LINE 999
void process_file(FILE* f)
{
char firstLine[MY_MAX_LINE + 1];
char secondLine[MY_MAX_LINE + 1];
while (1)
{
if (!fgets(firstLine, sizeof(firstLine), f))
break;
puts(firstLine);
if (!fgets(secondLine, sizeof(secondLine), f))
break;
if (strncmp(firstLine, secondLine, sizeof(firstLine)))
puts(secondLine);
}
if (!feof(f))
perror("Problem reading from file"), exit(1);
}
int main(int argc, char **argv)
{
FILE *f = fopen("text.txt", "r");
if (!f)
perror("text.txt"), exit(1);
process_file(f);
fclose(f);
return 0;
}

Read WORDS (not char) from file without empty lines in C - not duplicated [duplicate]

This question already has an answer here:
Read text from file skipping any spaces or empty lines
(1 answer)
Closed 8 years ago.
Hi.
I need to read several files without empty lines between words.They can have different layouts, such as 1.txt or 2.txt:
1.txt:
treg
hreger
ig
srg
fre
ig
lre
eg
2.txt:
lregreg
igregr
kreggerg
ereherh
tershs
hsehsteh
asreh
treshse
How do i do that ? How can I count the number of words in the fastest way?
I just have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
FILE *fp;
char palavra[50]="/0";
char *s;
fp = fopen("1.txt","r");
if(fp == NULL){
puts("Open file failed\n");
exit(-1);
}
while(fscanf(fp,"%s",palavra)!=EOF){
s=palavra;
/*do things with s var*/
}
fclose(fp);
exit(0);
}
how i implement something like that:
while ((c = fgetc(fp)) != EOF) {
if (isspace(c)){
continue;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
enum status { OUT, IN };
int main(){
FILE *fp;
int ch, wc = 0, stat = OUT;
if(NULL==(fp = fopen("1.txt","r"))){
fprintf(stderr, "Open file failed\n");
exit(-1);
}
while(EOF!=(ch=fgetc(fp))){
if(isspace(ch)){
stat = OUT;
} else {
if(stat == OUT){
stat = IN;
++wc;
}
}
}
fclose(fp);
printf("number of words is %d.\n", wc);
return 0;
}

Unable to read a file and pass into arguments

1) I'm trying to open a file, read the mix data (ints, chars and strings) and store them into args.
1.1) so in the sample.txt is a total of 13 (excluding args[0])
2) Need to read a file from terminal "./myprog.c < sample.txt"
Heres my code and have no idea where i went wrong:
sample.txt:
123 213 110 90 1
hello my friend
boo bleh
a b c
myprog.c:
#include <stdio.h>
int main()
{
int i = 1;
FILE *fstin=fopen(argv[0], "r"); //open the file
if (fstin == NULL) {
puts("Couldn't fopen...");
return -1;
}
//Getting all the inputs from file
while ((fscanf(fstin, "%d", argv[i])) != EOF){
i++;
}
fclose(fstin);
for (i=0; i<10; i++) {
printf("%d\n",argv[i]);
}
return 0;
}
Any help is greatly appreciated!
PS: Would like if anyone could post their complete solution? Will upload unto this post and let everyone have a review of this problem
PPS: Please excuse the poor level of coding as I am a beginner and completely new to C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int ac, char *av[]){
int i, argc=0;
char **argv=NULL, data[16];
FILE *fstin = stdin;
if(ac == 2){
if(NULL==(fstin = fopen(av[1], "r"))){
puts("Couldn't fopen...");
return -1;
}
}
while (1==fscanf(fstin, "%15s", data)){
argv = realloc(argv, (argc+1)*sizeof(char*));
argv[argc] = malloc(strlen(data)+1);
strcpy(argv[argc++], data);
}
if(ac == 2)
fclose(fstin);
for (i=0; i<argc; ++i) {
printf("%s\n", argv[i]);
}
//deallocate
return 0;
}
You are making mistake at 2nd point where you divert your file to other file which is wrong. Actually you need to first compile and need to make executable.
gcc -o my_prog ./myprog.c -Wall
You need to execute this program as below to read file from c program:
./my_prog ./sample.txt
As you are new to C programming first go to man pages related to file operations.
Solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
//If command line argument is not inserted then stop operation
if (2 != argc) {
printf("Invalid number of arguments : %d\n", argc);
return -1;
}
int size = 0, ret = 0;
char *data = NULL;
FILE *fp = NULL;
//Open file in read mode given from command line argument
if (NULL != (fp = fopen(argv[1], "r")))
{
//Find size of file
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
//if file is empty no need to read it.
if (size > 0)
{
//Data pointer which contains file information
data = (char *) calloc(sizeof(char), size);
if (NULL != data)
{
//Read whole file in one statement
fread(data, sizeof(char), size, fp);
printf("File %s is readed successfully\n", argv[1]);
printf("Data:\n");
printf("%s\n", data);
free(data); data = NULL;
}
else
{
perror("memory allocation failed\n");
ret = -1;
}
}
else
{
printf("File %s is empty\n", argv[1]);
}
fclose(fp); fp = NULL;
}
else
{
perror("File open failed\n");
ret = -1;
}
return ret;
}
Now Test it on your setup and if any query please post comments.

C programming, calling a function

I am new to C and i am trying to iteratively call line in stream and check to see if it contains my search string or if it is null. I cant figure out how to make this check, i get a warning saying [Warning] comparison between pointer and integer or [Warning] assignment makes pointer from integer without a cast whenever i try and do this. can anyone help? thanks.
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
FILE *fpntr;
char *file_pathname, *first_line;
if (argc != 2) {
fprintf(stderr, "usage: %s FILE\n", argv[0]);
return EXIT_FAILURE;
}
file_pathname = argv[1];
if ((fpntr = fopen(file_pathname, "r")) == NULL ) {
fprintf(stderr, "Error opening file %s: %s\n", file_pathname, strerror(errno));
return EXIT_FAILURE;
} else {
grep_stream();
fclose(fpntr);
}
return EXIT_SUCCESS;
}
int grep_stream(FILE *fpntr, char *string, char *file_pathname) {
//warning is on next line
while ((? = get_next_line(fpntr)) == NULL ) {
perror("Error reading line");
exit(EXIT_FAILURE);
}
elseif()
{
printf("First line in : %s \n %s", file_pathname, string);
}
}
char *get_next_line(FILE *fpntr) {
char *buff = malloc(101);
int pos = 0;
int next;
while ((next = fgetc(fpntr)) != '\n' && next != EOF) {
buff[pos++] = next;
}
buff[pos] = '\0';
if (buff != NULL ) {
return buff;
} else
return NULL ;
}
Remember that C code is compiled top-to-bottom. The function get_next_line isn't declared by the time the while line is read.
Either move get_next_line's definition to before main's, or forward-declare it by saying:
char *get_next_line(FILE *fpntr);
beforehand. The reason that you're getting a warning instead of an error is that undeclared functions are assumed to return int and no assumptions are made about their parameters. That is, they have the type int().
Also, properly format your code for both your sake and of those who will be answering your questions (or working with you.)
add a * to the pointer of integer to convert it from pointer to integer
... i am trying to iteratively call line in stream...
Why not use fgets()?
Secondly, to match a substring in a string, you can use strstr()
Please use standard C library instead of re-inventing the wheel. It saves the day usually.
#include <assert.h> // I'm too dumb to program without assertions!
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
//#include <unistd.h> I prefer stdlib.h, couldn't see any need for non-portable header...
#define MAX_LINE (101) // define funky constants in one place for easy changing later.
// declare functions before using them
void grep_stream(FILE *fpntr, char *file_pathname);
char *get_next_line(FILE *fpntr);
int main(int argc, char *argv[]) {
FILE *fpntr;
char *file_pathname;
if (argc != 2) {
fprintf(stderr, "usage: %s FILE\n", argv[0]);
return EXIT_FAILURE;
}
file_pathname = argv[1];
if ((fpntr = fopen(file_pathname, "r")) == NULL ) {
fprintf(stderr, "Error opening file %s: %s\n", file_pathname, strerror(errno));
return EXIT_FAILURE;
}
else {
grep_stream(fpntr, file_pathname);
fclose(fpntr);
}
return EXIT_SUCCESS;
}
void grep_stream(FILE *fpntr, char *file_pathname) {
char* line;
int got_first = 0;
assert(fpntr);
assert(file_pathname); // I worry the guy who wrote main() might be an idiot like me!
//warning is on next line [not anymore!]
while ((line = get_next_line(fpntr)) != NULL ) {
if(!got_first) {
printf("First line in : %s \n%s\n", file_pathname, line);
got_first = 1;
}
// if we're not going to use it, let's not leak memory
free(line);
}
}
char *get_next_line(FILE *fpntr) {
char *buff = malloc(MAX_LINE);
int pos = 0;
int next;
assert(buff != NULL); // wouldn't it be nice to know malloc() worked?
while ((next = fgetc(fpntr)) != '\n' && next != EOF) {
buff[pos++] = (char)next;
assert(pos < (MAX_LINE-1)); // don't want to be right back on SO with a seg fault, eh?
}
buff[pos] = '\0';
if(next == EOF) {
free(buff);
buff = NULL;
}
return buff;
}

Resources