Copying Only Part of a File to a New One in C - c

I have a practice question in C that asks me to create a function that only copies part of a file to another one. The restrictions are that lines with greater than maxlen characters are not copied to the new file, and the newline character does not count, so it should not be copied. Part of my function says that if a file does not exist, it should explicitly say so, and I am getting those error messages when I run that code; however, I can see that the files are created are inside my folder. Whenever I open the file I'm trying to read after running the code, I get this:
./Debug/main.c.o ./Debug/dot.c.o ./Debug/dataBase.c.o ./Debug/intPrompt.c.o ./Debug/numWords.c.o ./Debug/LinkedList.c.o
Below is my code :
void shortLines(char* f1, char* f2, int maxlen) {
FILE* fp = fopen(f1, "r");
FILE* fp2 = fopen(f2, "w");
if (fp == NULL) {
perror("File does not exist");
}
if (fp2 == NULL) {
perror("File does not exist");
}
char singleLine[maxlen];
char check;
size_t len;
do {
fgets(singleLine, maxlen, fp);
len = strlen(singleLine);
if (singleLine[len-1] == '\n') {
singleLine[len-1] = '\0';
}
fprintf(fp2, "%s", singleLine);
} while ((check=getc(fp) != EOF));
}
int main(int argc, char **argv) {
shortLines("Andrew.txt", "Andrew2.txt", 25);
return 0;
}

I just made new files called Andrew.txt and Andrew2.txt and these ones seem to be working for some strange reason. Regardless, there were a few problems in the code. First of all, after fgets is called, I needed to make sure to flush out the remaining characters in the line. I do this with a while loop and fgetc. If I reach an EOF, then I continue, and then fgets also returns an EOF, thus breaking the outer loop.
void shortLines(char* f1, char* f2, int maxlen) {
FILE* fp = fopen(f1, "r");
FILE* fp2 = fopen(f2, "w");
if (fp == NULL) {
perror(f1);
}
if (fp2 == NULL) {
perror(f2);
}
char line[maxlen+1];
size_t len;
char c;
while (fgets(line, maxlen+1, fp) != NULL) {
len = strlen(line);
if (len == maxlen) {
while ((c=fgetc(fp)) != '\n') {
if (feof(fp)) {
break;
}
}
continue;
}
if (line[len-1] == '\n') {
line[len-1] = '\0';
}
fprintf(fp2, "%s\n", line);
}
}

Related

Read one file and write to another C

I am trying to read from files and write to a temp file. However, I am stuck in an infinite loop right now. The function below is called multiple times by a recursive function that goes through directories to read files.
My approach is that I would read each word from one file, then those words to another file.
The function I have works fine if I just print out each word. It prints out each word in each file in all directories. However, when I try to start writing to a temp file (the code commented out), I am stuck in the while loop.
On the other hand, if I just call the function once in a test program where I just read from one file in the current directory, and write to a temp file, it's fine.
This is what I have (fileName when passed in is actually the absolute path, and I do ../tmp so it does not get caught in the recursion function):
void fileReadWrite(char *pattern, char *before, char *replace, char *fileName) {
FILE *file = fopen(fileName, "r");
if (file != NULL) {
int ch, word = 0;
while ((ch = fgetc(file)) != EOF) {
if (isspace(ch) || ispunct(ch)) {
if (word) {
word = 0;
putchar('\n');
}
}
else {
word = 1;
putchar(ch);
/*
FILE *f = fopen("../tmp", "wb"); // create and write
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "Some text"); // Or fprintf(f, ch);
fclose(f);
*/
}
}
fclose(file);
}
}
There's nothing in your code that suggests an infinite loop. However, if fileName is very large, you could be opening and closing "..\tmp" millions of times. As Joachim Pileborg points out in the comments, you should open that file just once at the beginning of your function, and close it again at the end.
If you want to convince yourself that you are not in an infinite loop, print out the value of ch on each iteration.
Okay so I did this and it worked. But I don't understand why though. Can someone explain it please?
void fileReadWrite(char *pattern, char *before, char *replace, char *fileName) {
FILE *file = fopen(fileName, "r");
FILE *f = fopen("../tmp", "wb"); // MOVE HERE
if (file != NULL) {
int ch, word = 0;
while ((ch = fgetc(file)) != EOF) {
if (isspace(ch) || ispunct(ch)) {
if (word) {
word = 0;
putchar('\n');
}
}
else {
word = 1;
putchar(ch);
/*
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "Some text"); // Or fprintf(f, ch);
*/
}
}
fclose(file);
fclose(f); // MOVE HERE
}
}

How to get back pointer of pointers from a function

I have a function which open a file, read its content line by line and then push it to an array. I have managed to get the array functionnal inside the right function, but when I want to get it back to my main function, I cannot get any items of my array.
Some code will help you to understand:
My main function:
/* ----------------- MAIN ------------ */
int main(int argc, char *argv[]) {
/*... some useless code for now ... */
char **ptrLines = NULL;
ptrLines = readEventFile(ptrParam, ptrLines);
outputExecTrace(WAR, "PTRLINES x : %x", ptrLines);
outputExecTrace(WAR, "PTRLINES char[] : %s", *(ptrLines + 2));
return EXIT_SUCCESS;
}
My fileReader function:
char** readEventFile(Parameters *parameters, char **arrLine) {
FILE *fp = fopen(parameters->inputFilePath, "r");
if (fp == NULL)
exit(0);
char line[128];
int nbCharOfLine = 0;
while(1) {
fgets(line, sizeof(line), fp);
if (feof(fp))
break;
nbCharOfLine++;
}
fclose(fp);
arrLine = malloc(sizeof(line) * nbCharOfLine);
nbCharOfLine = 0;
fp = fopen(parameters->inputFilePath, "r");
while(1) {
fgets(line, sizeof(line), fp);
if (line[0] != '#') {
arrLine[nbCharOfLine] = malloc((strlen(line)+1) * sizeof(char));
strcpy(arrLine[nbCharOfLine], line);
nbCharOfLine++;
}
if (feof(fp))
break;
}
fclose(fp);
outputExecTrace(WAR, "ARRLINE x : %x", arrLine);
outputExecTrace(WAR, "ARRLINE char[] : %s", *(arrLine + 2));
return arrLine;
}
Has it is, my outputs are the followings:
WARNING: ARRLINE int : -2020552688
WARNING: ARRLINE char[] : 1 3 4 //This is the result I am looking for.
WARNING: PTRLINES int : -2020552688 // Same as ARRLINE
Segmentation fault (core dumped) // And this is because ptrLines[2] doesn't contains anything... but why ?!
How can I fix this ?
It's hard to tell exactly what happen, because you have several small problems within code, which could lead to this, try to change your code in following way:
char** readEventFile(char* fileName) {
char line[128];
int nbCharOfLine = 0;
FILE *fp = fopen(fileName, "r");
if (fp == NULL)
exit(1);
while (!feof(fp)) {
char *r = fgets(line, sizeof(line), fp); // NOTE: proper handling of fgets return value
if ((r != NULL) && (line[0] != '#'))
nbCharOfLine++;
}
fclose(fp);
char **arrLine = calloc(nbCharOfLine, sizeof(char*)); // use calloc to be sure
nbCharOfLine = 0;
fp = fopen(fileName, "r");
while (!feof(fp)) {
char *r = fgets(line, sizeof(line), fp);
if ((r != NULL) && (line[0] != '#')) {
arrLine[nbCharOfLine] = calloc(strlen(line) + 1, sizeof(char));
strcpy(arrLine[nbCharOfLine++], line);
}
}
fclose(fp);
return arrLine;
}
in your main, you will call this function like:
char **ptrLines = readEventFile(ptrParam->inputFilePath);
Not so sure this is the whole problem, but the posted code:
while(1) {
fgets(line, sizeof(line), fp);
if (line[0] != '#') {
arrLine[nbCharOfLine] = malloc((strlen(line)+1) * sizeof(char));
strcpy(arrLine[nbCharOfLine], line);
nbCharOfLine++;
}
if (feof(fp))
break;
}
is not the right approach for several reasons,
including that function feof()
is only asserted 'true' when the code has tried to read past the
end of the file.
suggest:
while( fgets(line, sizeof(line), fp) )
{
if (line[0] != '#')
{
if( NULL == (arrLine[nbCharOfLine] = malloc((strlen(line)+1) * sizeof(char)) ) )
{ // then, malloc failed
perror( "malloc failed" );
// close file and free all malloc'd areas
exit( EXIT_FAILURE );
}
// implied else, malloc successful
strcpy(arrLine[nbCharOfLine], line);
nbCharOfLine++;
}
}

Pass stream by reference

I am suppose to pass stream, which is a pointer, by reference. So I am passing this as a pointer to a pointer. Can someone please verify my code?
int main(int argc, char** argv)
{
FILE *stream;
printf("LINES: %d\n",scan(stream));
}
int scan(FILE *(*stream))
{
stream = fopen("names.txt", "r");
int ch = 0, lines=0;
while (!feof(*stream))
{
ch = fgetc(*stream);
if (ch == '\n')
{
lines++;
}
}
fclose(*stream);
return lines;
}
No output received.
Your code has design issues. What exactly do you want to achieve?
If you just want to count the lines, make the FILE * local to your function:
int count_lines(const char *filename)
{
FILE *stream = fopen(filename, "r");
int lines = 0;
while (1) {
int c = fgetc(stream);
if (c == EOF) break;
if (c == '\n') lines++;
}
fclose(stream);
return lines;
}
If you want to do a regular file operation (read, write, seek, rewind etc.) to a file that has already been opened with fopen, just pass the handle as FILE *:
int fget_non_space(FILE *stream)
{
int c;
do {
c = fgetc(stream);
} while (isspace(c));
return c;
}
In that case, both fopen and fclose are called outside this function. (You don't call fclose in your program, which you should, even if the operating system makes sure to close the file automatically after exiting.)
Passing a pointer to the file handle, FILE **, makes sense only if you want to change that file handle itself in the function, for example by calling fopen:
int fopen_to_read(FILE **FILE pstream, const char *fn)
{
*pstream = fopen(fn, "r");
return (*pstream != NULL) ? 0 : -1;
}
Even then, it would be better to return the file handle, as fopen does.
Your example code leaves the open filehandle accessible in main, but you don't do anything with it, you don't even close it. Is that what you want? I doubt it.
Use
int scan(FILE **stream) //no need for brackets
{
*stream = fopen("names.txt", "r"); //* is for dereferencing
if(*stream==NULL) // Checking the return value of fopen
{
printf("An error occured when opening 'names.txt'");
return -1;
}
int ch = 0, lines=0;
while ((ch = fgetc(*stream))!=EOF) //while(!feof) is wrong
{
if (ch == '\n')
{
lines++;
}
}
fclose(*stream); // Close the FILE stream after use
return lines;
}
int main(void)
{
FILE *stream;
printf("LINES: %d\n",scan(&stream)); //Pass address of `stream`. The address is of type `FILE**`
}
Replace
stream = fopen("names.txt", "r");
with
*stream = fopen("names.txt", "r");
Also
printf("LINES: %d\n",scan(stream));
with
printf("LINES: %d\n",scan(&stream));

How to write text from file to a string in C

I want to write code were the user is asked to write the name of a file. Then I want to analyze the file's content for a symbol, let's say 'e'.
My problem is that I don't know how to start analyzing the file the correct way so that the content can be checked.
int main() {
char c[1000], file_name[1000];
int i;
int s = 0;
FILE *fp;
printf("Enter the name of file you wish to see\n");
gets(file_name);
if ((fp = fopen(file_name, "r")) == NULL){
printf("Error! opening file");
exit(1);
}
if (fp) {
while (fscanf(fp, "%s", c) != EOF) {
printf("%s", c);
}
fclose(fp);
for (i = 0; c[i] != '\0'; ++i) {
puts(c);
if (c[i] == 'e') {
++s;
}
}
printf("\nWhite spaces: %d", s);
_getche();
return 0;
}
}
char line[512]; /*To fetch a line from file maximum of 512 char*/
rewind(fp);
memset(line,0,sizeof(line)); /*Initialize to NULL*/
while ( fgets(line, 512, fp ) && fp !=EOF)
{
/*Suppose u want to analyze string "WELL_DONE" in this fetched line.*/
if(strstr(line,"WELL_DONE")!=NULL)
{
printf("\nFOUND KEYWOD!!\n");
}
memset(line,0,sizeof(line)); /*Initialize to null to fetch again*/
}
If its just a symbol you're looking for, or a char, you can simply use getc() :
int c;
....
if (fp) {
while ((c = getc(fp)) != EOF) {
if (c == 'e') {
// Do what you need
}
}
Or, alternatively, if it's a word you're looking for, fscanf() will do the job:
int c;
char symb[100];
char symbToFind[] = "watever"; // This is the word you're looking for
....
while ((c = fscanf(fp, %s, symb)) != EOF) {
if (strcmp(symb, symbToFind) == 0) { // strcmp will compare every word in the file
// do whatever // to symbToFind
}
}
These alternatives will allow you to search every char or string in the file, without having to save them as an array.

C language-weird output using fgets

here's the code in question:
FILE *fp;
char str[256];
/* opening file for reading */
fp = fopen("file.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
while( fgets (str, sizeof(str), fp)) {
int i;
char *temp;
temp=malloc(257);
for(i=0;i<sizeof(str)-1;i++){
if(isalpha(str[i])){
append(temp,str[i]);
}else{
printf(" %s ",temp);
temp=calloc(257,sizeof(char));
}
}
}
if the text file is the following:
"Here's a text
file example. No
idea what's wrong."
then it will output the following:
"Here s a text vf file example No vf idea what s wrong".
Desired output for reference:
"Here s a text file example No idea what s wrong"
Basically some weird stuff every time there's a newline involved. Could be "vf" when i run it. Could be "ZG" the next time. It changes every time i run the program.
Reading parts of buf not filled by fgets()`.
Replace
// for(i=0;i<sizeof(str)-1;i++)
for(i=0;i<strlen(str);i++)
or better
// for(i=0;i<sizeof(str)-1;i++)
size_t len = strlen(str);
// removed potenital ending '\n'
if ((len > 0) && (str[len-1] == '\n')) len--;
size_t i;
for (i = 0; i < len; i++)
Perhaps I didn't understand what you're doing but if you just want to read the whole file in one string you can do something like this
int main(int argc, const char * argv[])
{
FILE *fp;
char str[256];
char *temp = calloc(257, 1);
fp = fopen("file.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
while( fgets (str, sizeof(str), fp)) {
int i;
//char *temp;
if (str[strlen(str)-1] == '\n') {
str[strlen(str)-1] = ' ';
}
strncat(temp, str, 257);
}
puts(temp);
}
There is no problem with fgets. It automatically appends terminating null character.
Also you do not free memory before allocating new. It's not good.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char str[256];
/* opening file for reading */
fp = fopen("file.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
while( fgets (str, sizeof(str), fp)) {
int i;
char temp[256]; //buffer; can allocate on the stack, no need for malloc
char *temp1; //pointer at the beginning of the buffer (used to do my own append())
temp1=temp; //for my own appending
for(i=0;i<sizeof(str);i++){
int ch=str[i]; //alias the str[i]
if(isalpha(ch)||ch=='"'){ //let these chars thru
*temp1++=ch; //my own append()
}else if(ch=='\0'){//already at the end of buffer, end loop and print
*temp1=ch; //don't forget to end the string with '\0' (for printing functions)
break;
}else if(ch=='.'){ // you seem to want to skip dots
continue;
}
else {
*temp1++=' '; //replace other nonalpha characters with ' '
}
}
printf("%s",temp);
}
}

Resources