C- Reading specific strings with quotes from a file - c

I am trying to read strings from a file. File contains below text:
<1a>This is line 1<1a>
<2f>This is line 2<2f>
<3c>This is line 3<3c>
In my program I get this value 1a or 2f. Based on this, I need to extract that particular line like for 2f, I only need to read This is line 2 and save it in a buffer.
I have been able to read write using fopen fput but dont know how to read this.Can anyone please point me into some right direction which shows how to read this. Any demo code. Thanks.

This should do the trick:
#include <stdio.h>
#include <string.h>
int extract_line (char* line, char* buffer, char* ctag)
{
char line_buffer[255] = {0};
char* tagStart;
char* tagEnd;
if( strlen(line) < (sizeof(line_buffer)/sizeof(char)) )
{
strcpy(line_buffer,line);
}
else
{
printf("Line size is too big.\n");
return 1;
}
tagStart = strstr(line_buffer,ctag);
if(tagStart != NULL)
{
tagEnd = strstr(tagStart+1,ctag);
if(tagEnd != NULL && (tagEnd > (tagStart + strlen(ctag))))
{
*(tagEnd) = '\0';
strcpy(buffer, tagStart + strlen(ctag));
printf("%s\n",buffer);
}
else
{
printf("Could not find closing tag.\n");
return 1;
}
}
return 0;
}
int main ()
{
char buffer[255] = {0};
char line_buffer[255] = {0};
char tag[] = "<2a>";
char* cptr;
FILE* data;
data = fopen ("file.txt", "r");
if (data == NULL)
{
printf("\n Failed to open file!");
}
else {
while(( fgets( line_buffer, 255, data )) != NULL)
{
cptr = strstr(line_buffer,tag);
if(cptr == NULL)
{
continue;
}
if(!extract_line(line_buffer,buffer,tag))
{
//Do the rest of processing
puts(buffer);
strcpy(buffer,"");
}
}
fclose (data);
}
return 0;
}
Basicly, what you need to do is get the tag field and use it as a delimeter to exctract the token. Just get the line tag and then use it to exctract the data.

char* returnSpecificString(char* valueBetweenQuotes)
{
FILE* file= fopen("test.txt", "r"); // Open in reading only mode
char *line= malloc(sizeof(char[150]));
if (NULL == line) // Checks if enough memory
fprintf(stderr, "Not enough memory. \n");
else
{
while(fgets(line, sizeof(line), file)) //Iterate until end of file
{
if (strstr(line, valueBetweenQuotes) != NULL) // Meaning it's the line we want
return functionToExtractTextBetweenQuote();
}
}
return line;
}
As for the functionToExtractTextBetweenQuote() I advise you look functions like strtok() strchr()or sprintf() which will help you extract what you want from a string. I know this is unsufficiant but I ain't got the time to finish it now so I hope it will help you.

Related

How to copy lines up to a certain character from one text file into another in C?

I have a text file, "input", in which some lines contain the character '$'. I want to copy this file into a new text file, "output", but with all the lines truncated after (and including) the '$' character (if present).
I have tried the following:
while (fgets(line, LINE_LENGTH, input) != NULL)
{
strcpy(tmp_line, line);
cmt_ptr = strchr(tmp_line, '$');
if (cmt_ptr != NULL)
{
*cmt_ptr = '\n';
}
fputs(tmp_line, output);
}
This compiles, but all the text after '$' in each line gets copied into a new line.
I then tried this:
while (fgets(line, LINE_LENGTH, input) != NULL)
{
strcpy(tmp_line, line);
cmt_ptr = strchr(tmp_line, '$');
if (cmt_ptr != NULL)
{
strtok(tmp_line, '$');
}
fputs(tmp_line, output);
}
but I get an error message saying "Access violation reading location".
Can someone please advise me on how to correct the code?
Below code is insufficient as only the $ is substituted with a '\n'. To shorten the string, set a null character. #Some programmer dude
if (cmt_ptr != NULL)
{
*cmt_ptr = '\n';
cmt_ptr[1] = '\0'; // Add
}
Alternative approach: Use different ways to print when a $ is found. No tmp_line needed.
while (fgets(line, LINE_LENGTH, input) != NULL) {
char *cmt = strchr(line, '$');
if (cmt) {
int length = cmt - line;
printf("%.*s\n", length, line); // Print limited character array.
} else {
fputs(line, output);
}
}
Using fgets is over-complicating the issue, since there's no need to read full lines. Just read one character at a atime. eg:
#include <stdlib.h>
#include <stdio.h>
FILE * xfopen(const char *path, const char *mode);
int
main(int argc, char **argv)
{
FILE *input = argc > 1 ? xfopen(argv[1], "r") : stdin;
FILE *output = argc > 2 ? xfopen(argv[2], "w") : stdout;
enum { print, noprint } state = print;
int c;
while( (c = getc(input)) != EOF ){
switch( c ){
case '$':
state = noprint;
break;
case '\n':
state = print;
}
if( state == print ){
putc(c, output);
}
}
return 0;
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}

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
}
}

Reading specific line from file

I am trying to read a specific line from a file using the code below.
char *getlinenum(char *filename, int lnum)
{
FILE *f;
int i;
char *linebuf = NULL, *tmp = NULL;
if ((f = fopen(filename, "r")) != NULL)
{
linebuf = (char *)malloc(2048);
memset(linebuf, 0, 2048);
for (i = 0; i < lnum; i++)
{
if (fscanf(f, "%[^\n]\n", linebuf) == EOF)
{
free(linebuf);
fclose(f);
printf("Returning NULL\n");
return NULL;
}
}
//tmp = strdup(linebuf);
//free(linebuf);
fclose(f);
return linebuf;
}
return NULL;
}
No matter what, this is always returning just an empty (zero) string. Any issues you see? Here is the test file:
/home/mainframe/b
/home/mainframe/dead.letter
/home/mainframe/.bash_history
/home/mainframe/a
/home/mainframe/f
/home/mainframe/e
/home/mainframe/c
/home/mainframe/g
/home/mainframe/.ssh/authorized_keys
/home/mainframe/.ssh
/home/mainframe/d
I don't really understand where it could end up with a zero string (not a nullpointer).
This code is working for me (made no changes except removing uncesessary tmp variable)
One issue is if 0 is passed, the for loop never enters. Just change it to <= and/or add another if-statement at the beginning:
if( lnum <= 0 )
return NULL;
to catch this issue.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *getlinenum(char *filename, int lnum)
{
FILE *f;
int i;
char *linebuf = NULL;
if( lnum <= 0 )
return NULL;
if ((f = fopen(filename, "r")) != NULL)
{
linebuf = (char *)malloc(2048);
memset(linebuf, 0, 2048);
for (i = 0; i <= lnum; i++)
{
if (fscanf(f, "%[^\n]\n", linebuf) == EOF)
{
free(linebuf);
fclose(f);
printf("Returning NULL\n");
return NULL;
}
}
free(linebuf);
fclose(f);
return linebuf;
}
return NULL;
}
int main()
{
printf("%s\n", getlinenum("input.txt", 2));
return 0;
}
Output:
/home/mainframe/dead.letter
A fairly obvious problem not mentioned yet is that this code overflows the buffer if there is a line longer than 2048.
Another problem is that your fscanf string will skip blank lines (except for the first line of the file). I'm not sure if this was intentional. The \n matcher that you have on the end of the string means to match all whitespace up till the next non-whitespace even if that whitespace includes multiple newlines.
To fix that problem, you could remove that \n and just do a fgetc() after each fscanf to consume one newline.
To fix the buffer overflow I would recommend skipping up to the line you want without storing anything, and then using a fgets to get the line you are interested in. For example (here I also have factored out the cleanup code):
if (lnum < 1 || (f = fopen(filename, "r")) == NULL)
return NULL;
char *buffer = NULL;
for ( ; lnum > 1; --lnum )
{
if ( fscanf(f, "%*[^\n]") == EOF || fgetc(f) == EOF )
break;
}
if ( lnum == 1 )
{
// or use the POSIX getline() function or similar, to avoid any size limitation and
// avoid the mucking around with fgets and \n
buffer = calloc(1, 2048);
if ( ! fgets(buffer, 2048, f) )
{
free(buffer);
buffer = NULL;
}
else if ( buffer[0] && buffer[strlen(buffer)-1] == '\n' )
buffer[strlen(buffer)-1] = 0;
}
fclose(f);
return buffer;
Also, using unsigned long long for line_num would let you read more!

print a certain line of a file in c

I am trying to print a certain line of a file in c. So far I think I am successfully reading line 8 of my text file but my question is how do I print that line using this code?
Thanks!!
this is the code so far:
int lineNumber = 8;
static const char filename[] = "Text.txt";
FILE *file = fopen(filename, "r");
int count = 0;
if ( file != NULL )
{
char line[256]; /* or other suitable maximum line size */
while (fgets(line, sizeof line, file) != NULL) /* read a line */
{
if (count == lineNumber)
{
//use line or in a function return it
//in case of a return first close the file with "fclose(file);"
}
else
{
count++;
}
}
fclose(file);
}
This works perfectly fine.
Are you missing the main function OR is it just the code snippet you have posted ?
int lineNumber = 8;
static const char filename[] = "Text.txt";
int main()
{
FILE *file = fopen(filename, "r");
int count = 0;
if ( file != NULL )
{
char line[256]; /* or other suitable maximum line size */
while (fgets(line, sizeof line, file) != NULL) /* read a line */
{
if (count == lineNumber)
{
//use line or in a function return it
// //in case of a return first close the file with "fclose(file);"
printf("\n str %s ", line);
fclose(file);
return 0;
}
else
{
count++;
}
}
fclose(file);
}
return 0;
}

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