I am facing problems scanning an existing file.
The challenge is that I have a source text file with some strings. I have to scan this file for the word "o'clock", and where I find it, I have to take the word before "o'clock" and enclose it in square brackets.
I found a function to find the trigger, but I don't understand what I need to do next. I would be grateful if you could explain how to replace the characters in the read string.
For example: We have a string:
"Let's go to the graveyard at night - at twelve o'clock!"
I need to replace the word twelve with [twelve].
Here is the code:
#include <stdio.h>
#include <string.h>
int main() {
FILE * fp; //open exists file
FILE * fn; //open empty file
char c[1000]; // buffer
char trigger[] = "o'clock"; // the word before which the characters should be added
char name [] = "startFile.txt"; // name of source file
char secondName[] = "newFile.txt"; // name of output file
fp = fopen (name, "r"); // open only for reading
if (fp == NULL) { // testing on exists
printf ( "Error");
getchar ();
return 0;
}
fn = fopen(secondName, "w"); // open empty file for writing
while (!feof(fp)) { // scanning all string in the source
if(fgets(c,1000, fp) != NULL) { // reading charter from file
fprintf(fn, c); // writing charter from buffer "c" to empty file
if (strstr(c, trigger)) { // find triggered word
// I tried compare string which has a trigger-word
}
}
}
fclose(fp); // closing file
fclose(fn);
return 0;
}
In your code, you copy the line to the output file and then, afterwards, look for the trigger word. But the goal is to find the trigger and edit the string, and only then write the line to the output file. Also, in order to edit the line, you need to know where the trigger was found so you need to save the output of the search.
So, instead of:
fprintf(fn, c); // writing charter from buffer "c" to empty file
if (strstr(c, trigger)) { // find triggered word
// I tried compare string which has a trigger-word
}
We need:
char *p = strstr(c, trigger);
if (p) {
// I tried compare string which has a trigger-word
}
fputs(c, fn); // writing charter from buffer "c" to empty file
So now we found the trigger and we need to search backwards to find the end and then the start of the word before it. When we find them we need to create a spot and insert the edits:
char *p = strstr(c, trigger);
if (p) {
// ok we found the trigger - now we need to search backwards
// to find the end and then the start of the word before
while (p>c && p[-1]==' ') p--; // find the end of the word
memmove(p+1, p, c+999 - p); // make a space for the ]
*p = ']';
while (p>c && p[-1]!=' ') p--; // find the start of the word
memmove(p+1, p, c+999 - p); // make a space for the [
*p = '[';
}
fputs(c, fn); // writing charter from buffer "c" to empty file
Try it here: https://www.onlinegdb.com/H18Tgy9xu
But then, what if there was more than one "o-clock" in the string? Something like this:
Let's go to the graveyard at twelve o'clock and have dinner at six o'clock beforehand!
In that case, you need to loop around until you have found all of them:
Here is the final code:
#include <stdio.h>
#include <string.h>
int main() {
FILE * fp; //open exists file
FILE * fn; //open empty file
char c[1000]; // buffer
char trigger[] = "o'clock"; // the word before which the characters should be added
char name [] = "startFile.txt"; // name of source file
char secondName[] = "newFile.txt"; // name of output file
fp = fopen (name, "r"); // open only for reading
if (fp == NULL) { // testing on exists
printf ( "Error");
getchar ();
return 0;
}
fn = fopen(secondName, "w"); // open empty file for writing
if (fn == NULL) { // testing on create
printf ( "Error");
getchar ();
return 0;
}
while (fgets(c, 1000, fp)) { // scanning all string in the source
char *p = c; // we need to start searching at the beginning
do {
p = strstr(p+1, trigger); // find the next oclock after this one
if (p) {
// ok we found the trigger - now we need to search backwards
// to find the end and then the start of the word before
while (p>c && p[-1]==' ') p--; // find the end of the word
memmove(p+1, p, c+999 - p); // make a space for the ]
*p = ']';
while (p>c && p[-1]!=' ') p--; // find the start of the word
memmove(p+1, p, c+999 - p); // make a space for the [
*p = '[';
p = strstr(p, trigger); // find that same oclock again
// (we couldn't save the location because memmove has changed where it is)
}
} while (p); // as long as we found one, search again
fputs(c, fn); // writing charter from buffer "c" to empty file
}
fclose(fp); // closing file
fclose(fn);
return 0;
}
Try it here: https://onlinegdb.com/SJMrP15ld
Related
The software intends to read from a csv styled file (it's delimited by space not by a comma) and split the initial file into two new ones. The two files are determined by the last field, which is a binary value. As it stands, it currently reads the file character by character. I want it to recognize the space, and only run the individual character check on the very last field. To my understanding, strtok() will come in handy, but I'm struggling to find a way to incorporate that into the existing software.
Any help would be greatly appreciated :)
/*
* C program to parse a file, and split it into two based on the final line of input
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Function declarations */
int isMale(signed char _line);
int isFemale(signed char _line);
int isMale(signed char _line)
{
}
int isFemale(signed char _line)
{
}
int main()
{
/* File pointer to hold reference to different files */
FILE * fPtrIn, // Input file
* fPtrMale, // Males of school age
* fPtrFemale, // Females of school age
* fPtrMisc; // Data not within the given parameters
// current_char is the current character being read
// success stores the read status
char current_char;
int success;
// Open all files to perform read/write.
fPtrIn = fopen("data/example.txt", "r");
fPtrMale = fopen("data/males.txt" , "w");
fPtrFemale = fopen("data/females.txt" , "w");
fPtrMisc = fopen("data/erroneus.txt", "w");
// fopen() return NULL if unable to open file in given mode.
if(fPtrIn == NULL || fPtrMale == NULL || fPtrFemale == NULL || fPtrMisc == NULL)
{
// Unable to open file, exit software
printf("Unable to open file.\n");
printf("Please check whether file exists and you have read/write privilege.\n");
exit(EXIT_FAILURE);
}
// File open success message
printf("File opened successfully. \n\n");
// Read an integer and store read status in success.
while (fscanf(fPtrIn, "%d", ¤t_char) != -1)
{
// Write each one to separate file
if (isMale(current_char))
fprintf(fPtMale, "%d\n", current_char);
else if (isFemale(current_char))
fprintf(fPtrFemale, "%d\n", current_char);
else
fprintf(fPtrMisc, "%d\n", current_char);
}
// Done with all files, hence close all.
fclose(fPtrIn);
fclose(fPtrMale);
fclose(fPtrFemale);
fclose(fPtrMisc);
printf("Data written to files successfully.");
return 0;
}
You should
Read lines via fgets()
Copy the line read because strtok() will modify original buffer.
parse fields via strtok()
Judge and output according to the parsed field.
// hoping that too long lines won't come
char line[102400], line_parse[102400];
// Read an integer and store read status in success.
while (fgets(line, sizeof(line), fPtrIn) != NULL)
{
char *last_field, *ret;
// Copy the line for parsing
strcpy(line_parse, line);
// Separate the line into tokens
last_field = ret = strtok(line_parse, " ");
while (ret != NULL)
{
last_field = ret;
ret = strtok(NULL, " ");
}
// Get the first character of the last field
if (last_field == NULL) current_char = '\0'; else current_char = last_field[0];
// Write each one to separate file
if (isMale(current_char))
fputs(line, fPtrMale);
else if (isFemale(current_char))
fputs(line, fPtrFemale);
else
fputs(line, fPtrMisc);
}
Im Completely new to programming but need to get a program running as part of my training. The programs ultimate goal is to read files from a database and then send them to the client who is asking for it.
Currently im just learning how to read strings from a file and write it to a different file. But my problem is that I want to print data out every time i hit a new line.
The data in the file im using is in the following format:
<DESCRIPTION>data,<DESCRIPTION>data,<DESCRIPTION>data etc.
The data is both int and chars.
Since the data is seperated with a "," i was thinking of first puting all "<DESCRIPTION>data" into substrings with the strtok function i managed to find while googling, after that i would scan only for the "DESCRIPTION" part and then put the desired data into an array that I then would print out when reaching the end of the array (end of the line) and then move on to the next line until End of file.
What functions can I use to fix this? Or how do I set up a loop that wont take forever by scanning all chars in the line everytime it wants data? If what im saying and what im doing is 2 different things I again apologize for being a total beginner at programming. I have been prgramming for a week now and this is all I could produce
#include <stdio.h>
#include <ctype.h>
void get9202() {
char
const * str;
const char s = ",";
char * token;
/*open database file*/
FILE * fp = fopen("datafile.dat", "r");
/*create array with all lines of data
I would like it to be able to handle unknown amounts of data.
current file is ~177000 lines of data.*/
int i = 0;
char line[i];
/*checking until end of file*/
while (fgets(line, sizeof(line), fp)) {
/*This part has to be included in the loop somehow but put in here
so that you might get a picture of what im trying to do.*/
while ( * str) {
if (!isspace( * str++))
i++;
else break;
/*not entirely sure how to exit this subloop
to print out the data and go to new line*/
}
/*trying to segment the string into an array of substrings
but dont know when to introduce x*/
token[x] = strtok(str, s);
while (token[x] != NULL) {
printf("%s\n,", token);
}
}
return result;
/* dont know how to return the file to main*/
flclose("datafile.dat");
}
If the data looks like this:
<SYMBOL>9202.T,<SYMSTAT>2,<MSGSTAT>0,<TIME>20:50:40.905246,<SYS_DT>2018/07/19,<SYS_TIM>20:50:40.503,<SYS_TIMU>20:50:40.503236
<SYMBOL>9202.T,<SYMSTAT>2,<MSGSTAT>0,<TIME>20:51:40.000235,<SYS_DT>2018/07/19,<SYS_TIM>20:51:39.598,<SYS_TIMU>20:51:39.598597
the expected file could look like
9202.T,2,0,20:50:40.905246
9202.T,2,0,20:51:40.000235
as the wanted pieces are being selected some will fall away.
Few problems:
Will declare zero length array.
int i=0;
char line[i];
fclose is never executed because of return also fclose needs FILE * as argument.
return result;
/* dont know how to return the file to main*/
flclose("datafile.dat");
Suggestions:
trying to segment the string into an array of substrings but dont
know when to introduce x
Use fgets with fscanf to parse your line since all the lines are identical.
dont know how to return the file to main
Define a structure with needed fields and return it to main.
Example:
typedef struct {
char symbol[50];
char symstat;
char msgstat;
char time[50];
}data;
data *get9202(int *numData) {
int memAllocated = 10;
data *mData = malloc(sizeof(*mData) * memAllocated);
FILE *fp = fopen("datafile.dat", "r");
char buf[3000];
int i = 0;
while (fgets(buf, sizeof buf, fp) != NULL) {
if (i == memAllocated) {
memAllocated *= 2;
void *temp = realloc(mData, sizeof( *mData) * memAllocated);
if (temp != NULL) mData = temp;
else break; //error
}
if (sscanf(buf, "<SYMBOL>%[^,],<SYMSTAT>%c,<MSGSTAT>%c,<TIME>%[^,]",
mData[i].symbol, &mData[i].symstat, &mData[i].msgstat, mData[i].time) == 4) {
i++;
} else {
printf("error\n"); //error
}
}
fclose(fp);
*numData = i;
return mData;
}
int main() {
int len = 0;
data *mData = get9202( &len);
int i = 0;
for (i = 0; i < len; i++)
printf("%s,%c,%c,%s\n", mData[i].symbol, mData[i].symstat, mData[i].msgstat,
mData[i].time);
if (mData) free(mData);
}
NOTE: I am a beginner so I don't know plenty of stuff.
The code is working fine. Its purpose is to translate a text file from language one (English) to language 2 (French) using the dictionary from language 1(char word[][]) and language 2(char replace[][]).
I just want to know how I could change it so I am using the line from a text file instead of the "word" and "replace" arrays.
Content of the "word" text file (let's say englishwords.txt):
Hello (this is going to be on the first line of the text)
What (this is going to be on the second line of the text)
You're (this is going to be on the third line of the text)
How are you (this is going to be on the fourth line of the text)
a fool (this is going to be on the fifth line of the text)
Content of the "replace" text file (let's say frenchwords.txt):
Salut (this is going to be on the first line of the text)
Quoi (this is going to be on the second line of the text)
Tu es (this is going to be on the third line of the text)
Ce va (this is going to be on the fourth line of the text)
un fou (this is going to be on the fifth line of the text)
Basically: one line in the text file = one word or correlated phrase
int main(){
FILE *fp1, *fp2;
char fname[MAX];
char string[MAX];
char temp[] = "temp.txt", *ptr1, *ptr2;
/* get the input file from the user */
printf("Enter your input file name: ");
fgets(fname, MAX, stdin);
fname[strlen(fname) - 1] = '\0';
int j = NULL;
do {
/* in-code dictionary */
char word[MAX][MAX] =
{
"Hello",
"What",
"You're",
"How are you",
"a fool"
};
char replace[MAX][MAX] =
{
"Salut",
"Quoi",
"Tu es",
"Ca va",
"un fou"
};
/* open input file in read mode */
fp1 = fopen(fname, "r");
/* error handling */
if (!fp1) {
printf("\nUnable to open the input file or it doesn't exist!\n");
return NULL;
}
/* open temporary file in write mode */
fp2 = fopen(temp, "w");
/* error handling */
if (!fp2) {
printf("\nUnable to open temporary file or it was erased!\n");
return NULL;
}
/* going through and replacing the objects */
j++;
while (fgets(string, sizeof string, fp1)) {
char *p = string;
int i;
while (*p) {
for (i = NULL; i < 5; ++i)
if (!strncmp(p, word[i], strlen(word[i])))
break;
if (i < 5) {
fputs(replace[i], fp2);
p += strlen(word[i]);
}
else {
putc(*p, fp2);
p++;
}
}
}
/* close the opened files */
fclose(fp1);
fclose(fp2);
/* remove the input file */
remove(fname);
/* rename temporary file name to input file name */
rename(temp, fname);
} while (j < 2);
return NULL;}
I guess this is how I start:
FILE *enw = fopen("englishwords.txt", "r");
FILE *frw = fopen("frenchwords.txt", "r");
But how do I do continue the resolve?
I am writing a program in C ..that opens a plain text file containing C-like source code, reads it, and outputs a file with the same content as the first, except that all comments are removed.The program must check that all brackets match,if they do not, the program should display an error message,at showing the type of error and the line number where this error was encountered.(I displayed an error message but how can i locate the error position..?) The input and output files are passed to the program a####nd line parameters, as in:
./your_executable inputfile.txt outputfile.txt
Here is the code that i wrote:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Functions */
void check_comment (char) ; // checks for both types of comments, then passes on control to below comments
void block_comment () ; // handles block or multiline comments
void single_comment () ; // handles single line comments
/* 2 file pointers - 1st is for the file in which we check for comments,
and 2nd is the file in which we copy the code after removing comments */
FILE *fp , *fp2;
int main(void)
{
char c;
fp = fopen ("inputfile.txt","r") ; // open the first file in read mode
fp2 = fopen ("outputfile.txt","w") ; // open the second file in write mode
while((c=fgetc(fp))!=EOF) // read the file character by character
check_comment(c); // check for each character if it seems like the beginning of a comment
// close both the files at the end of the program
fclose(fp);
fclose(fp2);
FILE *fp;
char fname[20];
char brackets[20] = "{}[]()";
int bracketCounts[6] = {0};
char * found;
int i;
printf("Please enter the destination of the file: \n");
scanf("%s", fname);
if ((fp = fopen(fname, "r")) == NULL){
printf("Problem opening file!\n");
return 0x00;
}
printf("File opened correctly\n");
// counting various parentheses
while ((c = getc(fp)) != EOF){
found = strchr(brackets, c);
if (found != NULL) {
bracketCounts[found - brackets]++;
}
}
// dont't forget to close file after reading is done
fclose(fp);
// checking parentheses counters
for (i=0; i < 6; i+=2) {
if (bracketCounts[i] != bracketCounts[i+1]) {
printf("Unbalanced parentheses !\n");
return 0x00;
}
}
printf("All parentheses are OK!\n");
return 0;
}
// function that handles both types of comments
void check_comment(char c)
{
char d;
if( c == '/') // if the character starts with '/', it 'could' be a comment
{
if((d=fgetc(fp))=='*') // if the next character we read is '*', it is the beginning of multiblock comment
block_comment(); // pass control to function that handles multiblock comments
else if( d == '/') // else if the next character we read is '/', it is the beginning of single line comment
{
single_comment();// pass control to function that handles single line comment
}
else
{
// if both the cases fail, it is not a comment, so we add the character as it is in the new file.
fputc(c,fp2);
fputc(d,fp2);
}
}
// again, if all above fails, we add the character as it is in the new file.
else
fputc(c,fp2);
}
// function that handles block comments
void block_comment()
{
char d,e;
while((d=fgetc(fp))!=EOF) // the block comment has started, read the character by character
{
/* keep reading the characters and do nothing,
as they do not have to be copied into the new file (we are removing the comments)
*/
if(d=='*') // if the comment 'seems' like ending
{
e=fgetc(fp); // check if it actually ends (block comments end with '*/')
if(e=='/') // if the comment 'has' ended, return from the function
return;
}
}
}
// function that handles single line comments
void single_comment()
{
char d,e;
while((d=fgetc(fp))!=EOF) // the single line comment has started, read the character by character
{
/* keep reading the characters and do nothing,
as they do not have to be copied into the new file (we are removing the comments)
*/
if(d=='\n') // check if the comment ends (single comments end with '\n', or newline)
return; // if the comment 'has' ended, return from the function
}
}
you can implement or use stack data structure, while reading input file if you get { , ( or [ push on the stack and if you get }, ) or ] pop the stack,at the end of input file stack should be empty then you get proper match else some mismatch happened.
along with paranthesis you can keep line numbers(or position, etc)
ex: 1 (
2 (somethig)
3 something),
push (, line1, then push (, line2 and when you get ) pop (, line2
and so on, in this case if you don't get second closing ), you can say that (, line1
is missing closing.
I'm trying to make a program that replacing strings in files.
I got the program below that replacing all the occurrences of one string in the file, but now I need to extend so it'll replace multiple strings.
The trivial way is to run the program several times, each time with different string as input, but I'm looking for more efficient way to do it.
My input can be:
Set of strings to replace (each string appears once).
List of strings to replace by order of appearance (string can be at the list several times) but without knowing their offset.
Thanks for the help.
#include <stdio.h>
#include <string.h>
#define LINE_LEN 128
int main(){
char fileOrig[32] = "orig.txt";
char fileRepl[32] = "new.txt";
char text2find[80];
char text2repl[80];
printf("enter text to replace in the file:");
scanf ("%s",text2find);
sprintf(text2repl,"%s%s%s","<b><font color=\"#FF0000\">",text2find,"</font></b>");
char buffer[LINE_LEN+2];
char *buff_ptr, *find_ptr;
FILE *fp1, *fp2;
int buff_int;
size_t find_len = strlen(text2find);
fp1 = fopen(fileOrig,"r");
fp2 = fopen(fileRepl,"w");
buff_int=(int)buffer;
while(fgets(buffer,LINE_LEN+2,fp1)){
buff_ptr = buffer;
while ((find_ptr = strstr(buff_ptr,text2find))){
while(buff_ptr < find_ptr)
fputc((int)*buff_ptr++,fp2);
fputs(text2repl,fp2);
buff_ptr += find_len;
}
fputs(buff_ptr,fp2);
}
fclose(fp2);
fclose(fp1);
return 0;
}
Sometimes things can get complicated. Say if you have strings to replace as {ab,ba} and they would be replaced to {xy,yx} respectively. Say you have the input file to contain "aba". Now the output becomes order dependant.
Similar confusion can occur if the replacement of one string causes another string to be formed which belongs to the strings-to-replace list.
IMO, you should define what you want to do in this situations and then use an approach similar to what you have already done.
BTW, you can better your string matching by using an finite automata based approach or use some existing state of the art algorithm like KMP or Boyer-Moore. This will let you search multiple strings at once.
I'm not sure if what you want is possible, but you might want to look into string search algorithms to make the search part of your algorithm more optimized. A naive search algorithm has, according to Wikipedia, complexity Θ((n-m+1) m), with n the length of your text and m the length of your search string. Take a look at the link, you can do significantly better.
Once you have all the offsets of the strings to replace, the actual replacing seems to be fairly straightforward.
I'm sorry I can't completely answer your question, but I thought this might give you some optimization ideas.
I think this will help you. Please use following Code to Search & Replace string .
Call this function from Top lavel function like this:
replaceIPAddress( "System.cfg", "172.16.116.157", "127.0.0.1");
void replaceIPAddress( char * confFileName, char *text_to_find , char *text_to_replace )
{
FILE *input = fopen(confFileName, "r");
FILE *output = fopen("temp.txt", "w");
char buffer[512];
while (fgets(buffer, sizeof(buffer), input) != NULL)
{
char *pos = strstr(buffer, text_to_find);
if (pos != NULL)
{
/* Allocate memory for temporary buffer */
char *temp = calloc(
strlen(buffer) - strlen(text_to_find) + strlen(text_to_replace) + 1, 1);
/* Copy the text before the text to replace */
memcpy(temp, buffer, pos - buffer);
/* Copy in the replacement text */
memcpy(temp + (pos - buffer), text_to_replace, strlen(text_to_replace));
/* Copy the remaining text from after the replace text */
memcpy(temp + (pos - buffer) + strlen(text_to_replace),
pos + strlen(text_to_find),
1 + strlen(buffer) - ((pos - buffer) + strlen(text_to_find)));
fputs(temp, output);
free(temp);
}
else
fputs(buffer, output);
}
fclose(output);
fclose(input);
/* Rename the temporary file to the original file */
rename("temp.txt", confFileName);
}
//
// Find and replace data in a file
//
// This is not as straightforward a problem as it initially appears,
// because if you have the text
//
// "Jack is a pirate"
//
// And you wish to replace "is" with "was", the string needs to be longer,
// or else you end up with the following:
//
// "Jack wasapirate"
//
// This becomes more of a problem for larger text. For example, if we wanted
// to replace "Jack" with "Rumpelstiltskin", we'd end up with:
//
// "Rumpelstiltskin"
//
// Which completely overwrites our original text!!!
//
// In order to do this correctly, we wither need to:
//
// 1. Read the entire file into a in-memory buffer
// 2. Write to a temporary file, then replace the original file
//
// Option #2 is easier to implement, and should work for your coursework.
//
#include <stdio.h>
int main(int argc, char** argv)
{
// We need a buffer to read in data
const int BufferSize = 0x1000;
char Buffer[BufferSize];
char *InputFileName = "input.txt";
char *TemporaryFileName = "temp.txt";
// Open the file for reading. 'rt' means that it must already exist, for reading.
FILE *Input = fopen(InputFileName, "rt");
// Our output file. 'w+' means to create the file if it doesnt exist, for writing.
FILE *Output = fopen(TemporaryFileName, "w+");
// Our find and replace arguments
char *Find = "is";
char *Replace = "was";
if(NULL == Input)
{
printf("Could not open file");
return 1;
}
printf("Find: %s\n", Find);
printf("Replace: %s\n", Replace);
// For each line...
while(NULL != fgets(Buffer, BufferSize, Input))
{
// For each incidence of "is"
char *Stop = NULL; // Where to stop copying (at 'is')
char *Start = Buffer; // Start at the beginning of the line, and after each match
printf("Line: %s\n", Buffer);
while(1)
{
// Find next match
Stop = strstr(Start, Find);
if(NULL == Stop)
{
// Print the remaining text in the line
fwrite(Start, 1, strlen(Start), Output);
break;
}
// Write out everything between the end of the previous match, and the
// beginning of the current match.
//
// For example:
//
// "Jack is a pirate who is cool"
//
// Has two instances to replace. In order, we'd find them as such:
//
// "Jack is a pirate who is cool"
// ^
// ^
// What we want to do is write:
// - "Jack "
// - "was"
// - "a pirate who "
// - "was"
// - "cool"
printf("Match starts at: %s\n", Stop);
// We have found a match! Copy everything from [Start, Stop)
fwrite(Start, 1, Stop - Start, Output);
// Write our replacement text
fwrite(Replace, 1, strlen(Replace), Output);
// Next time, we want to start searching after our 'match'
Start = Stop + strlen(Find);
printf("Search resumes at: %s\n", Start);
};
}
// Close our files
fclose(Input);
fclose(Output);
// If desired, rename the Output file to the Input file
rename(TemporaryFileName, InputFileName);
return 0;
}