This program attempts to save the contents of a text file into a character variable array. It is then supposed to use my_getline() to print the contents of the character array. I've tested and see that the contents are in fact getting saved into char *text but I can't figure out how to print the contents of char *text using my_getline(). my_getline is a function we wrote in class that I need to use in this program. When I attempt to call it in the way that was taught, it 1 is printed to terminal but then the terminal just waits and nothing else is printed. Any guidance would be appreciated. Also, let me know if I'm missing any information that would help.
/* Include the standard input/output and string libraries */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Define the maximum lines allowed in an input text and NEWLINE for getline funct. */
#define MAXPATTERN 15
#define MAXFILENAMELENGTH 15
#define NEWLINE '\n'
/* function prototypes */
void my_getline(char text[]);
int find_string(char text[], char pattern[], int length_text, int length_pattern);
int main()
{
FILE *fp;
long lSize;
char *text;
char fileName[MAXFILENAMELENGTH], pattern[MAXPATTERN];
char c;
int length_text, length_pattern, j, lineNumber = 1;
printf("Enter file name: ");
scanf("%s", fileName);
fp = fopen(fileName, "r");
if (fp == NULL)
{
printf("fopen failed.\n");
return(-1);
}
fseek(fp, 0L, SEEK_END);
lSize = ftell(fp);
rewind(fp);
/* allocate memory for all of text file */
text = calloc(1, lSize + 2);
if(!text)
{
fclose(fp);
fputs("memory allocs fails", stderr);
exit(1);
}
/* copy the file into text */
if(1 != fread(text, lSize, 1, fp))
{
fclose(fp);
free(text);
fputs("Entire read fails", stderr);
exit(1);
}
text[lSize + 1] = '\0';
printf("%s has been copied.\n", fileName);
rewind(fp);
printf("%d ", lineNumber);
for (j = 0; (j = getchar()) != '\0'; j++)
{
my_getline(text);
printf("%d %s\n", j+1, text);
}
printf("Enter the pattern you would like to search for: ");
scanf("%s", pattern);
printf("\nYou have chosen to search for: %s\n", pattern);
fclose(fp);
free(text);
return(0);
}
void my_getline(char text[])
{
int i = 0;
while ((text[i] = getchar()) != NEWLINE)
++i;
text[i] = '\0';
}
Your function is causing a system hang because you're calling getchar(), which returns the next character from the standard input. Is this really what you want?
At this point, your program is expecting input from the user. Try typing in the console windows and pressing to see it coming back from the "hang"
It is most likely causing an infinite loop because you are not checking whether you have reached EOF.
void my_getline(char text[])
{
int i = 0;
int c;
while ( (c = getchar()) != NEWLINE && c != EOF )
text[i++] = c;
text[i] = '\0';
}
Related
I'm trying to copy words from one file to another, but the words must begin with the given letter. It's working but doesn't copy every word that matches.
#include <stdio.h>
int main() {
FILE *f = fopen("words.txt", "r");
FILE *f2 = fopen("words_copy.txt", "a+");
char usr;
printf("enter letter: ");
scanf("%c", &usr);
char buffer[255];
char ch, ch2;
while ((ch = fgetc(f)) != EOF) {
ch2 = fgetc(f);
if (ch2 == usr && ch == '\n') {
fputc(ch2, f2);
fgets(buffer, sizeof(buffer), f);
fputs(buffer, f2);
}
}
return 0;
}
Words.txt contains:
adorable aesthetic alluring angelic appealing arresting attractive
blooming charismatic charming cherubic chocolate-box classy contagious
cute dazzling debonair decorative delectable delicate distinguished
enchanting enticing eye-catching glamorous glossy good-looking
gorgeous infectious lovely lush magnetic magnificent majestic melting
mesmerizing noble picturesque poetic prepossessing shimmering striking
stunning winsome
every word is in next line,
when I'm running the program and giving the letter m words_copy.txt contains only:
magnificent melting
How to fix to copy every word with matching letter?
The test in the loop is incorrect: you check the first letter after a newline and output the line if there is a match. With this logic:
you cannot match the first word in the file
you only match words starting with usr
and the word following a match is ignored
Furthermore, you ch and ch2 should be defined with type int to match EOF reliably, you should test for fopen failure and close the files after use.
You should use a simpler approach:
read a word
test if it contains the letter
output the word if it matches
Here is a modified version:
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char usr;
char buffer[256];
int ch = 0;
size_t pos;
FILE *f = fopen("words.txt", "r");
if (f == NULL) {
fprintf(stderr, "cannot open words.txt: %s\n", strerror(errno));
return 1;
}
FILE *f2 = fopen("words_copy.txt", "a+");
if (f2 == NULL) {
fprintf(stderr, "cannot open words_copy.txt: %s\n", strerror(errno));
fclose(f);
return 1;
}
printf("enter letter: ");
if (scanf(" %c", &usr) != 1) {
fprintf(stderr, "missing input\n");
fclose(f);
fclose(f2);
return 1;
}
while (ch != EOF) {
pos = 0;
/* read a word, stop at whitespace and end of file */
while ((ch = fgetc(f)) != EOF && !isspace(ch)) {
if (pos + 1 < sizeof(buffer))
buffer[pos++] = (char)ch;
}
buffer[pos] = '\0';
/* test for a match */
if (strchr(buffer, usr)) {
/* output matching word */
fprintf(f2, "%s\n", buffer);
}
}
fclose(f);
fclose(f2);
return 0;
}
Here's my task and below you can find my specific question and the code I wrote:
Write a program that reads strings and writes them to a file. The string must be dynamically
allocated and the string can be of arbitrary length. When the string has been read it is written to the
file. The length of the string must be written first then a colon (‘:’) and then the string. The program
stops when user enters a single dot (‘.’) on the line.
For example:
User enters: This is a test
Program writes to file: 14:This is a test
Question:
My code adds the number of characters and the colon, but not the string I typed, and when entered "." it wont exit
This is the code I have so far:
#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_SZ 256
int main() {
char key[] = ".";
char *text;
int i;
text = (char*)malloc(MAX_NAME_SZ);
FILE* fp;
do {
printf("Enter text or '.' to exit: ", text);
fgets(text, MAX_NAME_SZ, stdin);
for (i = 0; text[i] != '\0'; ++i);
printf("%d: %s", i);
fp = fopen("EX13.txt", "w");
while ((text = getchar()) != EOF) {
putc(text, fp);
}
fclose(fp);
printf("%s\n", text);
} while (strncmp(key, text, 1) != 0);
puts("Exit program");
free(text);
return 0;
}
There are many issues in your code, almost everything is wrong.
Just a few problems:
You use printf("%d: %s", i); to print on the screen what should go into the file.
The loop while ((text = getchar()) != EOF) doesn't make any sense.
You're closing the file after the first line entered
You ignore all compiler warnings
The end condition while (strncmp(key, text, 1) != 0) is wrong, you're only testing if the string starts with a ., and you're testing it too late.
This could be a start:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_SZ 256
int main() {
char* text;
int i;
text = (char*)malloc(MAX_NAME_SZ);
FILE* fp;
fp = fopen("EX13.txt", "w");
if (fp == NULL)
{
printf("Can't open file\n");
exit(1);
}
do {
printf("Enter text or '.' to exit: ");
fgets(text, MAX_NAME_SZ, stdin);
if (strcmp(".\n", text) == 0)
break;
for (i = 0; text[i] != '\0' && text[i] != '\n'; ++i);
fprintf(fp, "%d: %s", i, text);
} while (1);
fclose(fp);
puts("Exit program");
free(text);
return 0;
}
There is a limitation though, in this program the maximum line length is 254 characters, not including the newline character. As far as I understood, the line length must be arbitrary.
I let you do this on your own as an exercise, but at your C knowledge level it will be hard.
I think this should work for strings that are shorter than 255 chars.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_SZ 256
int main()
{
char key[] = ".\n";
char *text;
text = (char*)malloc(MAX_NAME_SZ);
if (text == NULL)
{
perror("problem with allocating memory with malloc for *text");
return 1;
}
FILE *fp;
fp = fopen("EX13.txt", "w");
if (fp == NULL)
{
perror("EX13.txt not opened.\n");
return 1;
}
printf("Enter text or '.' to exit: ");
while (fgets(text, MAX_NAME_SZ, stdin) && strcmp(key, text))
{
fprintf(fp, "%ld: %s", strlen(text) - 1, text);
printf("Enter text or '.' to exit: ");
}
free((void *) text);
fclose(fp);
puts("Exit program");
return 0;
}
In my code I'm trying to read a file, read it's lines and get them into a String array, then print them and close the file. When I run it, it fails on a seg fault and skips the last line of the file, and I just can't find the problem...
My instinct is to blame reading the array wrongly or misbehaving with the file... Am I right?
Any help or redirects would be helpful.
Thank you!
Here is the main file:
#include "files_utils.h"
int main()
{
FILE *fp = fopen("expl", "r");
if (!fp)
return -1;
long lines_count = countlines(fp);
long flen = file_length(fp);
String *lines = calloc(lines_count, sizeof(String));
printf("file length: %ld\n", flen);
printf("file lines: %ld\n", lines_count);
getlines(lines, lines_count, fp);
printf("finished\n");
for (String *sp = lines; sp != NULL; sp++)
printf("%s", *sp);
printf("before close\n");
fclose(fp);
printf("closed\n");
return 0;
}
Here is the files_utils file:
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 10
typedef char *String;
long file_length(FILE *fp)
{
/*
find the length of the file fp points to, regardless of the current position.
*/
long original_pos = ftell(fp), i = 0;
rewind(fp);
// count chars:
for (int c = fgetc(fp); c != EOF; c = fgetc(fp))
i++;
// return the file to it's original position
fseek(fp, original_pos, SEEK_SET);
return i;
}
long countlines(FILE *fp)
{
/*
find the amount of lines in file fp points to, regardless of the current position.
*/
long original_pos = ftell(fp), i = 0;
rewind(fp);
// find newlines:
for (int c = fgetc(fp); c != EOF; c = fgetc(fp))
if (c == '\n')
i++;
// return the file to it's original position
fseek(fp, original_pos, SEEK_SET);
return i;
}
String *getlines(String lines[], long maxlines, FILE *fp)
{
for (int i = 0; i <= maxlines; i++)
{
lines[i] = calloc(MAXLINE, sizeof(char));
fgets(lines[i], MAXLINE, fp);
}
return lines;
}
And it outputs
file length: 144
file lines: 21
finished
... all the lines of the file except of the last one ...
Segmentation fault (core dumped)
The problem was fixed when I changed the printing loop to run until maxlines instead of waiting for NULL. Why is this? Why would waiting for NULL raise a seg fault?
Supposing that I have two files like this:
file1.txt
john
is
the new
guy
file2.txt
man
the old
is
rick
cat
dog
I'd like to compare first line from file1 with all the lines from file2 and verify if it exist. If not, go two the second line from file1 and compare it with all the lines from file2.. and so on until eof is reached by file1.
The output that I expect is:
john
the new
guy
How I thought this should be done:
read file1 and file2
create a function which returns the line number of each of them
take the first line from file1 and compare it to all the lines from file2
do this until all the lines from file1 are wasted
Now, I don't know what I'm doing wrong, but I don't get the result that I expect:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int countlines(char *filename)
{
int ch = 0, lines = 0;
FILE *fp = fopen(filename, "r");
if (fp == NULL)
return 0;
do {
ch = fgetc(fp);
if (ch == '\n')
lines++;
} while (ch != EOF);
if (ch != '\n' && lines != 0)
lines++;
fclose(fp);
return lines;
}
int main(int argc, char *argv[])
{
FILE *template_file = fopen(argv[1], "r");
FILE *data_file = fopen(argv[2], "r");
char buffer_line_template_file[100];
char buffer_line_data_file[100];
if (argc != 3)
{
perror("You didn't insert all the arguments!\n\n");
exit(EXIT_FAILURE);
}
if (template_file == NULL || data_file == NULL)
{
perror("Error while opening the file!\n\n");
exit(EXIT_FAILURE);
}
int counter = 0;
for (int i = 0; i < countlines(argv[1]); i++)
{
fgets(buffer_line_template_file, 100, template_file);
for (int j = 0; j < countlines(argv[2]); j++)
{
fgets(buffer_line_data_file, 100, data_file);
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0)
{
counter++;
printf("%d", counter);
}
}
}
printf("\n\n");
return 0;
}
Could someone please point me into the right direction ? For testing purposes I created a counter at the end which was a part of a small debug. There should be the print() function
As per #chux answer I got the following simplified code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *template_file = fopen(argv[1], "r");
FILE *data_file = fopen(argv[2], "r");
char buffer_line_template_file[100];
char buffer_line_data_file[100];
if (argc != 3)
{
perror("You didn't insert all the arguments!\n\n");
exit(EXIT_FAILURE);
}
if (template_file == NULL || data_file == NULL)
{
perror("Error while opening the file!\n\n");
exit(EXIT_FAILURE);
}
while(fgets(buffer_line_template_file, 100, template_file))
{
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
rewind(data_file);
while (fgets(buffer_line_data_file, 100, data_file))
{
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0)
{
printf("%s\n", buffer_line_template_file);
}
}
}
printf("\n\n");
return 0;
}
The above code is giving me the following output, which is not what is expected:
john
john
john
john
john
john
is
is
is
is
is
the new
the new
the new
the new
the new
the new
guy
guy
guy
guy
guy
guy
Problems with OP's code
Imprecise definition of line.
Excessive recalculation
Fuzzy determination of the number of lines in a file.
Unlike string, which has a precise definition in C, reading a line is not so well defined. The primary specificity issue: does a line contain the trailing '\n'. If the first answer is Yes, then does the last text in a file after a '\n' constitute a line? (Excessively long lines are another issue, but let us not deal with that today.)
Thus possibly some lines end with '\n' and others do not, fooling strcmp("dog", "dog\n").
The easiest solution is to read a line until either 1) a '\n' is encountered, 2) EOF occurs or 3) line buffer is full. Then after getting a line, lop off the potential trailing '\n'.
Now all lines code subsequently works with have no '\n'.
fgets(buffer_line_template_file, 100, template_file);
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
OP's loop is incredible wasteful. Consider a file with 1000 lines. Code will loop, calling 1000 times countlines() (each countlines() call reads 1000 lines) times when one countlines() call would suffice.
// for (int j = 0; j < countlines(argv[2]); j++)
int j_limit = countlines(argv[2]);
for (int j = 0; j < j_limit; j++)
There really is no need to count the line anyways, just continue until EOF (fgets() returns NULL). So no need to fix its fuzzy definition. (fuzzy-ness concerns same issues as #1)
int counter = 0;
for (fgets(buffer_line_template_file, 100, template_file)) {
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
rewind(data_file);
while ((fgets(buffer_line_data_file, 100, data_file)) {
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0) {
counter++;
printf("%d", counter);
}
}
}
Other simplifications possible - for another day.
FWIW, following counts lines of text allowing the last line in the file to optionally end with a '\n'.
unsigned long long FileLineCount(FILE *istream) {
unsigned long long LineCount = 0;
rewind(istream);
int previous = '\n';
int ch;
while ((ch = fgetc(inf)) != EOF) {
if (previous == '\n') LineCount++;
previous = ch;
}
return LineCount;
}
Note that this function may get a different result that fgets() calls. Consider a file of one line of 150 characters. fgets(..., 100,...) will report 2 lines. FileLineCount() reports 1.
[Edit] Updated code to conform to OP functionality.
int found = 0;
while (fgets(buffer_line_data_file, 100, data_file))
{
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) == 0)
{
found = 1;
break;
}
}
if (!found) printf("%s\n", buffer_line_template_file);
This program prints the diff of two files file1.txt and file2.txt.
#include<stdio.h>
#include <stdlib.h>
#include <memory.h>
int main() {
FILE *fp1, *fp2;
int ch1, ch2;
char fname1[40], fname2[40];
char *line = NULL;
size_t len = 0;
ssize_t read;
char *line2 = NULL;
size_t len2 = 0;
ssize_t read2;
fp1 = fopen("file1.txt", "r");
fp2 = fopen("file2.txt", "r");
if (fp1 == NULL) {
printf("Cannot open %s for reading ", fname1);
exit(1);
} else if (fp2 == NULL) {
printf("Cannot open %s for reading ", fname2);
exit(1);
} else {
while ((read = getline(&line, &len, fp1)) != -1 && (read2 = getline(&line2, &len2, fp2)) != -1) {
if (!strcmp(line, line2)) {
printf("Retrieved diff on line %zu :\n", read);
printf("%s", line);
}
}
if (ch1 == ch2)
printf("Files are identical \n");
else if (ch1 != ch2)
printf("Files are Not identical \n");
fclose(fp1);
fclose(fp2);
}
return (0);
}
You already have a very good answer (and always will from chux), but here is a slightly different approach to the problem. It uses automatic storage to reading file2 into an array of strings and then compares each line in file1 against every line in file2 to determine whether it is unique. You can easily convert the code to dynamically allocate memory, but for sake of complexity that was omitted:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXC = 256, MAXL = 512 };
void file1infile2 (FILE *fp2, FILE *fp1, size_t *n2, size_t *n1);
int main (int argc, char **argv) {
FILE *fp1 = fopen (argc > 1 ? argv[1] : "file1.txt", "r");
FILE *fp2 = fopen (argc > 2 ? argv[2] : "file2.txt", "r");
size_t n1 = 0, n2 = 0;
if (!fp1 || !fp2) {
fprintf (stderr, "error: file open failed.\n");
return 1;
}
printf ("\nunique words in file1, not in file 2.\n\n");
file1infile2 (fp2, fp1, &n2, &n1);
printf ("\nanalyzed %zu lines in file1 against %zu lines in file2.\n\n",
n1, n2);
return 0;
}
void file1infile2 (FILE *fp2, FILE *fp1, size_t *n2, size_t *n1)
{
char buf[MAXC] = "";
char f2buf[MAXL][MAXC] = { "" };
size_t i;
*n1 = *n2 = 0;
while (*n2 < MAXL && fgets (buf, MAXC, fp2)) {
char *np = 0;
if (!(np = strchr (buf, '\n'))) {
fprintf (stderr, "error: line exceeds MAXC chars.\n");
exit (EXIT_FAILURE);
}
*np = 0;
strcpy (f2buf[(*n2)++], buf);
}
while (*n1 < MAXL && fgets (buf, MAXC, fp1)) {
char *np = 0;
if (!(np = strchr (buf, '\n'))) {
fprintf (stderr, "error: line exceeds MAXC chars.\n");
exit (EXIT_FAILURE);
}
*np = 0, (*n1)++;
for (i = 0; i < *n2; i++)
if (!(strcmp (f2buf[i], buf)))
goto matched;
printf (" %s\n", buf);
matched:;
}
}
Look over the code and let me know if you have any questions.
Example Use/Output
$ ./bin/f1inf2 dat/f1 dat/f2
unique words in file1, not in file 2.
john
the new
guy
analyzed 4 lines in file1 against 6 lines in file2.
I'm new at C and recently finished my work with files. I tried to create a program which will find an entered name in a file but it does not work. Could you try to repair it? I'll be thankful.
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fr;
int i,p,counter,final,length,j,c,k = 0;
char name[256];
char buffer[1024];
fr = fopen("C:/Users/prixi/Desktop/HESLA.TXT","r");
while ((c = fgetc(fr)) != EOF)
counter++;
printf("Enter the name");
scanf("%s",&name);
length = strlen(name);
while (fscanf(fr, " %1023[^\n]", buffer) != EOF) {
for (i = 0; i <= counter; i++)
if (name[0] == buffer[i]){
for (j = 0;j < length; j++ )
if (name[j] == buffer[i+j])
p++;
else
p = 0;
/* The 2nd condition is there because after every name there is ' '. */
if (p == length && buffer[i+j+1] == ' ')
final = 1;
}
}
if ( final == 1 )
printf("its there");
else
printf("its not there");
return 0;
}
It loads the inside of the file to the buffer and then scans char by char depending on how long the file is. I know that it's inefficient and slow, but I have been learning C only for like 4 days. I would really like you to help me fixing my own code otherwise :D I probably wont be able to fall asleep.
There are a lot of way to search a string into a File.
Try this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *loadFile(const char *fileName);
int main (void) {
const char *fileName = "test.txt";
const char *stringToSearch = "Addams";
char *fileContent = loadFile(fileName);
if (strstr(fileContent, stringToSearch)){
printf("%s was Found\n",stringToSearch);
}else{
printf("%s was not Found\n",stringToSearch);
}
free(fileContent);
return 0;
}
char *loadFile(const char *fileName){
size_t length,size;
char *buffer;
FILE *file;
file = fopen (fileName , "r" );
if (file == NULL){
printf("Error fopen, please check the file\t%s\n",fileName);
exit(EXIT_FAILURE);
}
fseek (file , 0 , SEEK_END);
length = (size_t)ftell (file);
fseek (file , 0 , SEEK_SET);
buffer = malloc(length+1);
if (buffer == NULL){
fputs ("Memory error",stderr);
exit (2);
}
size = fread (buffer,1,length,file);
if (size != length){
fputs ("Reading error",stderr);
exit(3);
}
buffer[length] = '\0';
fclose (file);
return buffer;
}
Output:
Addams was Found
I have inside the file "test.txt" the following:
Michael Jackson
Bryan Addams
Jack Sparrow
There are multiple problems with your code. You did not post the variable definitions, so we cannot verify if they are used consistently, especially name that should be an array of char.
The main issue is this: you count the number of bytes in fr by reading it, but you do not rewind the stream before scanning it for instances of the string.