First off I am creating a program that will read lines of characters and find words (they don't have to have meaning, i.e 'ab' could be word ) and storing them in the appropriate data structure. I used trie structure to store the words. I am given a mapping file as a command line argument yet inside the mapping file I have two data files I need to gain information from. The usage interface is as follows: first(program name) <mappingfile>.
Inside the mapping file, there exists two data files: <dictFile> and <dataFile>. Im not sure how to read and store the information presented the two data files. So far I have the following:
#include <stdio.h>
#include<stdlib.h>
void readDict(FILE *dict_file){
}
int main(int argc, char *argv[]){
FILE* file;
if(argc != 2){ //error in inputing, not 2 files
printf("error\n");
return 0;
}
file = fopen(argv[1],"r" ); //reading the mapping file
input;
if(file == NULL){ //nothing inside file
printf("file does not exist\n");
return 0;
}
}
My goal is to have pointers point to respective data files in the mapping file which I can use for reading their contents.
I will be given the following input in the command line:
first(program name) <mappingfile>.
Inisde the mapping file contains the lines of two plain .txt files in the form
<dictFile> <dataFile>.
I wish to access both contents of <dictFile> and <dataFile>.. with pointers to the respective file.
If I understand your question correctly you want to parse a file where each line contains the filenames of two other files and then read from these. What you can do is use fgets to read your mapping file line by line. What you can do next is use the function strtok to split your string on a whitespace. I'll break it down for you step by step.
Firstly we want to open the mapping file for reading
if((file = fopen(argv[1],"r")) == NULL) {
perror("error opening file");
return 1;
}
This will try to open the mapping file specified by the command line arguments of your program and if it fails it will print a corresponding error message.
while(fgets(buf, sizeof(buf), file) != NULL) {
After we've opened the file we want to iterate through all the lines until we reach the end of the file and fgets will return NULL. fgets will put the current line into buf.
dictfilename = strtok(buf, " ");
datafilename = strtok(NULL, " ");
strtok(dictfilename, "\n"); /* Remove any trailing newlines */
strtok(datafilename, "\n");
We need to split the line read by fgets by a delimter (a whitespace) so we know which part corresponds to the dictfile and the datafile. This is done by using the strtok function which returns a pointer to the substring before the whitespace and when passing in NULL it will return a pointer to the substring after the whitespace. A slightly weird way of removing any trailing newlines is to use strtok and the newline as a delimiter.
if((dictfile = fopen(dictfilename,"r")) == NULL) {
fprintf(stderr, "error opening file %s: %s\n", dictfilename, strerror(errno));
return 1;
}
if((datafile = fopen(datafilename,"r")) == NULL) {
fprintf(stderr, "error opening file %s: %s\n", datafilename, strerror(errno));
return 1;
}
Very similiarly to how we open the mapping file, we now open the two files found on the current line read by fgets with "r" mode which opens for reading. If the file does not exist or cannot be found, the fopen call fails.
printf("Content of %s:\n", dictfilename);
while ((c = getc(dictfile)) != EOF)
putchar(c);
printf("\nContent of %s:\n", datafilename);
while ((c = getc(datafile)) != EOF)
putchar(c);
This is a very simple method of "dumping" the content of the files. It uses getc to read the next char from the file and prints it until it reads EOF. This is where you should do your own function.
fclose(dictfile);
fclose(datafile);
And don't forget to close the files afterwards or you will leak resources.
Finally here is the code on what I just described
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_LENGTH 100 // change this to the actual maximum length of your lines.
int main(int argc, char **argv){
FILE* file, *dictfile, *datafile;
char c;
char buf[MAX_LENGTH];
char *dictfilename, *datafilename;
if(argc != 2) {
fprintf(stderr, "Usage: %s <mapping file>\n", argv[0]);
return 0;
}
if((file = fopen(argv[1],"r")) == NULL) {
perror("error opening file");
return 1;
}
while(fgets(buf, sizeof(buf), file) != NULL) {
dictfilename = strtok(buf, " ");
datafilename = strtok(NULL, " ");
strtok(dictfilename, "\n"); /* Remove any trailing newlines */
strtok(datafilename, "\n");
if((dictfile = fopen(dictfilename,"r")) == NULL) {
fprintf(stderr, "error opening file %s: %s\n", dictfilename, strerror(errno));
return 1;
}
if((datafile = fopen(datafilename,"r")) == NULL) {
fprintf(stderr, "error opening file %s: %s\n", datafilename, strerror(errno));
return 1;
}
// do something with the files (e.g read all the content)
printf("Content of %s:\n", dictfilename);
while ((c = getc(dictfile)) != EOF)
putchar(c);
printf("\nContent of %s:\n", datafilename);
while ((c = getc(datafile)) != EOF)
putchar(c);
printf("\n");
// don't forget to close the files when you're done with them.
fclose(dictfile);
fclose(datafile);
}
fclose(file);
}
If I understand you correctly this should do it. Note that it assumes your filenames don't have any spaces. And if you want to use the "non secure" api's you need to add _CRT_SECURE_NO_WARNINGS to the project properties under Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions.
#include <stdio.h>
#include<stdlib.h>
void readDict(FILE *dict_file){
}
int main(int argc, char *argv[]){
FILE* file;
if(argc != 2){ //error in inputing, not 2 files
printf("error\n");
return 1;
}
file = fopen(argv[1],"r" ); //reading the mapping file
//input;
if(file == NULL){ //nothing inside file
printf("file does not exist\n");
return 1;
}
char dictFileString[256], dataFileString[256];
fscanf( file, "%255s %255s", dictFileString, dataFileString );
FILE *dictFile, *dataFile;
dictFile = fopen( dictFileString, "r" );
if (dictFile == NULL) {
printf( "%s does not exist\n", dictFileString );
fclose(file);
return 1;
}
dataFile = fopen( dataFileString, "r" );
if (dataFile == NULL) {
printf( "%s does not exist\n", dataFileString );
fclose(file);
fclose(dictFile);
return 1;
}
readDict(dictFile);
// The additional logic would be placed here.
fclose( dictFile );
fclose( dataFile );
// If you need to read additional file names then loop
// back up to read the next line of 'file'
fclose( file );
return 0;
}
Related
I have this code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* ptr = fopen("data.txt","r");
char filename[100];
if (ptr==NULL)
{
printf("no such file.");
return 0;
}
char buf[100];
while (fscanf(ptr,"%*s %*s %s ",buf)==1)
printf("%s\n", buf);
printf("Create a file \n");
scanf("%s", filename);
fptr2 = fopen(filename, "w");
if (fptr2 == NULL)
{
printf("Cannot open file %s \n", filename);
exit(0);
}
c = fgetc(fptr1);
while (c != EOF)
{
fputc(c, fptr2);
c = fgetc(fptr1);
}
printf("\nContents copied to %s", filename);
fclose(fptr1);
fclose(fptr2);
return 0;
}
}
It coppies full content from one file to another. I need to copy only strings that have 5 as the last character (3 column)
For example Data.txt looks like that:
Alex 10B 4
John 10A 3
Kate 10C 5
In file that I will create during execution has to be coppied only Kate 10C 5 string. I've been trying for hours but I don't know how to do this. Can you help me?
In the end of each line there is a newline character, (\n) you can use that to read line by line and copy only the ones that you want:
FILE* dest = fopen("out.txt", "w+"); // supressed null check for simplicity
char buf[100];
char* char_to_find;
// parse line by line
while (fscanf(ptr, " %99[^\n]", buf) == 1){
char_to_find = buf;
// reach the end of the line
while(*char_to_find){
char_to_find++;
}
//move one back
char_to_find--;
// if it's 5 save, if not move on
if(*char_to_find == '5' && *(char_to_find - 1) == ' '){
fputs(buf, dest);
}
}
Live demo
The problem is that the function call
while (fscanf(ptr,"%*s %*s %s ",buf)==1)
consumes the input from the input stream, so that it is no longer available for copying. You are only saving the contents of the last field, but all other data is lost.
I suggest that you read one line at a time into a memory buffer, by calling the function fgets in a loop. That way, you will process one line of input per loop iteration, and will be saving the contents of the entire line.
In every loop iteration, you can use sscanf on this memory buffer to determine whether the third field has the desired value, and if it does, then you copy the entire line to the output file. Otherwise, you do nothing and proceed to the next line (i.e. the next loop iteration).
char line[100];
//process one line of input per loop iteration
while ( fgets( line, sizeof line, input_file ) != NULL )
{
char third_field[20];
if (
//third field was successfully extracted
sscanf( line, "%*s%*s%19s", third_field ) == 1
&&
//third field contains the string "5"
strcmp( third_field, "5" ) == 0
)
{
//copy entire line to output file
fputs( line, output_file );
}
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* ptr = fopen("data.txt","r");
char filename[100];
if (ptr==NULL)
{
printf("no such file.");
return 0;
}
printf("Create a file \n");
scanf("%s", filename);
FILE* dest = fopen(filename, "w+"); // check for null like above
char buf[100];
char* char_to_find;
while (fscanf(ptr,"%99[^\n] ", buf) == 1){
char_to_find = buf;
while(*char_to_find != 0){
char_to_find++;
}
char_to_find--;
if(*char_to_find == '5'){
printf("%s\n", buf); // test ptint
fputs(buf, dest);
}
}
}
I am trying to repeatedly read a string from the command line and print it to a file. This is my code:
int main ()
{
FILE* fp=fopen("test.txt","w");
char* tofile[10];
while(1){
printf("cat: ");
scanf("%s",tofile);
fprintf(fp,"%s\n",tofile);
}
return 0;
}
It works just fine outside the loop. But inside, it just doesn't print.
The fprintf function returns the correct amount of characters it has to print.
Note: I know there's a similar question out there, but it hasn't been answered yet, and I hope my code can help in this matter since it's simpler.
Well first it doesn't seem that what you want is reading on the command line.
The command line what you write right when you execute your program such as:
./main things that are on the command line
What it seems you want to do is to read on the standard input.
What you should consider is to use the fgets function, as it has a limit of characters to be read, so that you can store them "safely" into a buffer, like your tofile.
As you want to read on the standard input you can use the stdin stream (which is a FILE* that is automatically created for every program)
The line goes
fgets(tofile, 10, stdin);
Your loop becoming :
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
meaning: as long as we can read on the standard input, print "cat :" and store what we just read in the file controlled by the stream pointer fp.
Some important stuff
When you try to open a stream it may fail and you should test it:
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
Right before exiting your main, you should also close the file and check if it has succeeded, like that for example:
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
The whole thing becomes:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
char tofile[10];
printf("cat: ");
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Improvements
I don't know if it is just a little program or it aspires to become a greater program.
In the last case you should consider using defines and not a magical number such as
#define BUFFER_MAX_SIZE 10
char tofile[BUFFER_MAX_SIZE];
while (fgets(tofile, BUFFER_MAX_SIZE, stdin) != NULL) { ... }
This helps for readability and makes the program less apt to debug when modifying such a size. Because with the define all the part of the code needing the size will still be fully functional without modifying them.
Please also keep in mind that your tofile acts as a buffer, and it's really a small buffer that can easily be overflowed.
This will work. fgets() returns the string it reads from the specified file pointer. If this string returns only a newline ("\n"), that means nothing was entered at stdin.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp = fopen("test.txt","w");
// always check if fopen() == null
if (!fp) {
fprintf(stderr, "Could not write to file\n");
return 1;
}
char tofile[30];
printf("cat: ");
while (fgets(tofile, 30, stdin)) {
if (strcmp(tofile, "\n") == 0)
break;
fprintf(fp, "%s", tofile);
printf("cat: ");
}
// always fclose()
fclose(fp);
return 0;
}
Edited code.
For an assignment I have to input text from 2 files line by line into a 3rd file. So file 1 line 1 would be file 3 line 1 and file 2 line would would be file 3 line 2. I have attempted to this but can not seem to get the lines from each file to alternate. I am only able to get lines from each file separately. Please help with any suggestions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *file1, *file2, *file3;
char line [1000]; /* or other suitable maximum line size */
// check to make sure that all the file names are entered
if (argc != 4) {
perror("Error: ");
printf("Not enough files were entered!\n");
exit(0);
}
file1 = fopen(argv[1],"r");;
file2 = fopen(argv[2],"r");
file3 = fopen(argv[3],"w");
// check whether the file has been opened successfully
if (file1 == NULL)
{
perror("Error: ");
printf("Cannot open file1 %s!\n", argv[1]);
exit(-1);
}
// check whether the file has been opened successfully
if (file2 == NULL)
{
perror("Error: ");
printf("Cannot open file2 %s!\n", argv[2]);
exit(0);
}
// check whether the file has been opened successfully
if (file3 == NULL)
{
perror("Error: ");
printf("Cannot open file3 %s!\n", argv[3]);
exit(0);
}
int count = 0;
while (1)
{
if(fgets(line, sizeof line, file1) != NULL)
{
count+=1;
fprintf(file3, line);
}
else
{
break;
}
if(fgets(line, sizeof line, file2) != NULL)
{
count++;
fprintf(file3, line);
}
else
{
break;
}
}
fclose (file1);
fclose (file2);
fclose (file3);
}
fprintf(FILE *, const char *format, ...) expects a format as the 2nd argument.
Using fprintf(file3, line); will invoke undefined behavior (UB) should line contain a '%' or at least a missing % if "%%" was encountered.
Use fputs()
// fprintf(file3, line);
fputs(line, file3);
Additional concerns for advanced coding:
If the source file contains a null character, using fgets() is insufficient as it does not report the length read. Other approaches include using fgetc(), fread() or non-standard C getline().
If an input file does not end with a '\n', that rump line may look like a pre-fix to the line read from the other file.
As OP has noted, line length's of about 1000+ are a problem.
Source files line-endings, should they not match the code's understanding of line-ending can cause issues.
I want to check if there are any duplicates in a .txt file. I've wrote a code but it's not running. I'm not sure about opening the norep.txt file in "a+" mode. The idea is to put the first word of my text in the norep.txt file, then compare every word in the text.txt with the words in norep.txt and copy only the words I need in the file.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fd;
FILE *ft;
char aux[30];
char aux1[30];
int len;
fd = fopen("c:\\text.txt", "r");
if (fd == NULL) {
puts("Error");
}
ft = fopen("c:\\norep.txt", "a+");
if (ft == NULL) {
puts("Error");
}
fscanf(fd, "%s", aux);
fprintf(ft, "%s", aux);
rewind(fd);
rewind(ft);
while (!feof(fd)) {
fscanf(fd, "%s", aux);
while (!feof(ft)) {
fscanf(ft, "%s", aux1);
len = strcmp(aux, aux1);
if (len != 0) {
fprintf(ft, "%s", aux);
}
}
rewind(ft);
}
return 0;
}
You should flush the output file before you rewind it.
fflush - flush a stream or fflush
Of course, this will not fix your problem because:
Note below that the manual says that reposition operations are ignored so that your attempt to read will always find the end of file.
append: Open file for output at the end of a file. Output operations
always write data at the end of the file, expanding it. Repositioning
operations (fseek, fsetpos, rewind) are ignored. The file is created
if it does not exist.
What you should probably do is create an internal memory table that keeps all the unique entries and write it out to a new file after all processing is done. As you read the fd file, check the list and add a new entry if it is not already in the list. Then after you have finished processing fd, then and only then write out your list. Of course, this may be too big depending on the size of your data file.
You could append each unique entry to the output file as you go. but you would need to have some method of checking the previous entries without trying to read the output file.
The usual way to go about this is to read the input file word for word, store the necessary information in some way and then, after you have read all information from the file, write the desired output to the output file.
A rough skeleton of that approach might look like this:
int main()
{
const char *infile = "text.txt";
const char *outfile = "norep.txt";
FILE *in;
FILE *out;
char word[30];
// (1) Read all words
in = fopen(infile, "r"); // .. and enforce success
while (fscanf(in, "%29s", word) == 1) {
// store word somewhere
}
fclose(in);
// (2) Determine unique words somehow
// (3) Write out unique words
out = fopen(outfile, "w"); // .. and enforce success
for (i = 0; i < nunique; i++) {
fprintf(out, "%s\n", unique[i]);
}
fclose(out);
return 0;
}
The actual algorithm to fin the unique words is missing from this incomplete skeleton code.
If you really want to test the words in a file for uniqueness without using additional memory beyond the current word, you can open the input file twice, with independent file pointers. Then you can write a loop like so:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
const char *infile = "text.txt";
const char *outfile = "norep.txt";
FILE *in1;
FILE *in2;
FILE *out;
char word1[30];
char word2[30];
in1 = fopen(infile, "r");
in2 = fopen(infile, "r");
out = fopen(outfile, "w");
if (in1 == NULL || in2 == NULL || out == NULL) {
fprintf(stderr, "Could not open all required files.\n");
exit(1);
}
while (fscanf(in1, "%29s", word1) == 1) {
int count = 0;
while (fscanf(in2, "%29s", word2) == 1) {
if (strcmp(word1, word2) == 0) count++;
if (count > 1) break;
}
if (count == 1) fprintf(out, "%s\n", word1);
rewind(in2);
}
fclose(in1);
fclose(in2);
fclose(out);
return 0;
}
This will, of course, re-read the file as often as there are words in the file. Not a good approach to find the unique words in Moby-Dick. I recommend that you look into the memory-based approach.
I want to read a text file line by line, perform some checks, and if the line is not required, delete it.
I have done the code for reading line, but I don't know how to delete that line if it is not required by me.
Please help me find the simplest method for deleting the line.
Here is my code snippet what I tried:
char ip[32];
int port;
DWORD dwWritten;
FILE *fpOriginal, *fpOutput;
HANDLE hFile,tempFile;
hFile=CreateFile("Hell.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
tempFile=CreateFile("temp.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
WriteFile(hFile,"10.0.1.25 524192\r\n\r\n10.0.1.25 524193\r\n\r\n",strlen("10.0.1.25 524192\r\n\r\n10.0.1.25 524193\r\n\r\n"),&dwWritten,0);
fpOriginal = fopen("Hell.txt", "r+");
fpOutput = fopen("temp.txt", "w+");
while (fscanf(fpOriginal, " %s %d", ip, &port) > 0)
{
printf("\nLine1:");
printf("ip: %s, port: %d", ip, port);
char portbuff[32], space[]=" ";
sprintf(portbuff, "%i",port);
strcat(ip," ");
strcat(ip,portbuff);
if(port == 524192)
printf("\n Delete this Line now");
else
WriteFile(tempFile,ip,strlen(ip),&dwWritten,0);
}
fclose(fpOriginal);
fclose(fpOutput);
CloseHandle(hFile);
CloseHandle(tempFile);
remove("Hell.txt");
if(!(rename("temp.txt","Bye.txt")))
{
printf("\ncould not rename\n");
}
else
printf("\nRename Done\n");
//remove ("Hell.txt");
here's an example:
char* inFileName = "test.txt";
char* outFileName = "tmp.txt";
FILE* inFile = fopen(inFileName, "r");
FILE* outFile = fopen(outFileName, "w+");
char line [1024]; // maybe you have to user better value here
int lineCount = 0;
if( inFile == NULL )
{
printf("Open Error");
}
while( fgets(line, sizeof(line), inFile) != NULL )
{
if( ( lineCount % 2 ) != 0 )
{
fprintf(outFile, "%s", line);
}
lineCount++;
}
fclose(inFile);
fclose(outFile);
// possible you have to remove old file here before
if( !rename(inFileName, outFileName) )
{
printf("Rename Error");
}
You can copy all line wich does not contain the number 2 into a new file and then use the new file instead the old file
fp = fopen("File.txt", "r");
fp2 = fopen("File_copy.txt", "w");
while (fscanf(fp, " %s %d", string, &number) > 0) {
if(number != 2)
{
fprintf(fp2, "%s %d\n", string, number);
}
}
close(fp);
close(fp2);
remove("File.txt");
rename( "File_copy.txt", "File.txt" );
Another solution could be to write back to the same file (write back what you read out except for the lines you don't want) and use the Windows API function SetEndOfFile to truncate it when finished. This will probably be a bit messier to code but you won't need to create a second copy of the file so it's more efficient from a disk usage standpoint.
There are many to solve this problem one of them is, you can open another file for writing when you reach at a point where you don't want to write omit that paint and continue writing until end of file. Latterly you can delete old file and rename new file with old one.
if(number == 2)
{
continue;
}
else
{
writetofilefunction()
}