How to compare string from file and stdin string - c

I need to make program that checks if string inputted from console matches any string from input file and in my case it only works if i enter string that's last line in input file and i dont know why
int n;
char c[20];
char broj[20];
FILE* input;
input = fopen("input.txt", "r");
scanf("%s", broj);
while(fgets(c, 200, input) != NULL)
{
if(strcmp(c, broj) == 0)
printf("%s", c);
}
printf("\n");
fclose(input);
return 0;

As some have pointed out, you are reading too much into your buffer.
I really do not like to see the use of sizeof operator when calculating buffer sizes as the results can change depending on context.
void printSizeofTest1(char *test1) {
printf("Size of test1: %d\n", sizeof(test1));
}
int main() {
char *test = NULL;
char test1[10] = { 0 };
char test2 = '\0';
printf("Size of test: %d\n", sizeof(test));
printf("Size of test1: %d\n", sizeof(test1));
printf("Size of test2: %d\n", sizeof(test2));
printSizeofTest1(test1);
return 0;
}
Size of test: 4
Size of test1: 10
Size of test1: 1
Size of test1: 4
And you see this often when copying and pasting code.
Instead, it's far better to define the length of your pointers as macro expressions and always add a NULL byte pad for signed chars. And never reference it via sizeof but via the macro. This also means that if you need to change the size of the buffer, you only need to change it in one place.
With regards to your question. It's difficult without seeing the input file, however, when you use fgets it's going to pull back any new line ending characters, which may not necessary represent your input.
#include <stdio.h>
#include <string.h>
#define BUFF_SIZE 20
int main() {
char c[BUFF_SIZE+1] = { 0 },
broj[BUFF_SIZE+1] = { 0 };
FILE *input = fopen("input.txt", "r");
if(NULL != input) { /* <- Test for NULL file pointer */
scanf("%20s", broj); /* <- Provide a width specifier to avoid buffer overflow */
while(fgets(c, BUFF_SIZE, input) != NULL) {
printf("Searching for: %s\nFound: %s\n", broj, c);
if(strcmp(c, broj) == 0)
printf("%s", c);
memset(c, '\0', BUFF_SIZE); /* <- Clear buffer to ensure consistent search results */
}
fclose(input);
input = NULL; /* <- Assign to NULL so that you can check to see if it's closed */
}
printf("\n");
return 0;
}
In this example, I never find the contents of my file because my search is looking for a new line character which does not exist in my search string.
Instead, you should:
Remove the new line encodings from the file
Ignore the new line encodings
Search for precisely what you are looking for

Related

How to read from a file and parse it

I have a file .txt containing some values formatted like this:
0,30,25,10
Now, I open up the file and store it into an array
char imposta_tratt[300];
FILE *fp;
fp = fopen("/home/pi/Documents/imposta_trattamento.txt", "r");
if (fp == 0) return;
fread(imposta_tratt, sizeof(imposta_tratt), 1, fp);
fclose(fp);
Now I expect to have the array filled with my data. I have the values separated by a , so I go on and parse it:
const char delim[2] = ",";
int t=0;
char *token = strtok(imposta_tratt, delim);
while (token!=NULL){
strcpy(tratt[t],token);
token = strtok(NULL, delim);
tratt[t]=token;
t++;
}
Here, referring to what's in the file .txt, I expect to have tratt[0]=0; tratt[1]=30; tratt[2]=25; and so on, but seems like I am missing something since it's not like this.
All I want is to have the values of the txt file stored in single variables. Can someone help?
What you are trying to achieve can simply be done using fgets():
bool read_file_content(const char *filename, const size_t tsizemax, int tratt[tsizemax], size_t *tsize, const char *delim)
{
// Attempt to open filename.
FILE *fp = fopen(filename, "r");
if (!fp) return false; // Return false upon failure.
// Try to read one line. If you have more, you need a while loop.
char imposta_tratt[300];
if (!fgets(imposta_tratt, sizeof imposta_tratt, fp)) {
fclose(fp);
return false;
}
*tsize = 0;
char tmp[300]; // Temporary buffer. Used for conversion into int.
char *token = strtok(imposta_tratt, delim);
while (token && *tsize < tsizemax) {
strncpy(tmp, token, sizeof tmp);
tratt[(*tsize)++] = atoi(tmp);
token = strtok(NULL, delim);
}
fclose(fp);
return true;
}
const char *filename: The file you want to parse.
const size_t tsizemax: The maximum size of your tratt array. It is important to control the size, otherwise your code will have buffer overflow (think of when your file has more than 100 tokens, for example).
int tratt[tsizemax]: The array that will hold the values.
size_t *tsize: The number of tokens read (used in combination of tsizemax).
const char *delim: The delimiter(s), in your case a ,.
This is your main():
int main(void)
{
int tratt[100];
size_t size = 0;
if (!read_file_content("in.txt", 100, tratt, &size, ",")) {
puts("Failed");
return 1;
}
for (size_t i = 0; i < size; ++i)
printf("%d\n", tratt[i]);
}
Output:
0
30
25
10
Suppose "in.txt" has contents
0,30,25,10
The below program uses fscanf to read the integers into the tratt array, one-by-one. As we read integers using fscanf, we make sure it's return value is as expected. If not, we close the file and exit. In the event that the return value of fscanf is not as expected, the program also prints which type of error occurred. Currently, if any error occurs, the program stops. However, you can make the program behave differently depending on the error that occurred if you like.
As output, the program prints all of the integers read into the tratt array. The output is
0
30
25
10
Now this program assumes we know the number of elements we want to read into tratt. If we do not, we could allow for dynamically allocating more memory should the array need more elements or perhaps "in.txt" could contain a data structure, say, at the beginning/end of the file that records information about the file, such as the number of numbers in the file and the data type (a binary file would be best suited for this). These are just a couple of the possibilities.
A better approach might be to read characters in one-by-one (say, using getc) and use strtol to convert a sequence of character digits to a long int (I would have taken an approach similar to this).
Nevertheless, this approach is more succinct and should suffice.
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "in.txt"
#define MAX_LEN 4
int main(void) {
int i, tratt[MAX_LEN];
FILE *fp = fopen(FILE_NAME, "r"); /* open file for reading */
/* if cannot open file */
if (fp == NULL) {
printf("Cannot open %s\n", FILE_NAME);
exit(EXIT_FAILURE);
}
/* read integer, checking return value of scanf as expected */
if (fscanf(fp, "%d", &tratt[0]) != 1) {
if (ferror(fp))
printf("fscanf: read error\n");
else if (feof(fp))
printf("fscanf: end of file\n");
else
printf("fscanf: matching failure\n");
fclose(fp);
exit(EXIT_FAILURE);
}
for (i = 1; i < MAX_LEN; i++)
/* read comma plus integer, checking return value of scanf */
if (fscanf(fp, ",%d", &tratt[i]) != 1) {
if (ferror(fp))
printf("fscanf: read error\n");
else if (feof(fp))
printf("fscanf: end of file\n");
else
printf("fscanf: matching failure\n");
fclose(fp);
exit(EXIT_FAILURE);
}
fclose(fp); /* close file */
/* print integers stored in tratt */
for (i = 0; i < MAX_LEN; i++)
printf("%d\n", tratt[i]);
return 0;
}

Read a file specified as an argument and return its' lines

I have an exercise in which I have to read a file containing strings and I have to return the content using one/multiple arrays (this is because the second part of this exercise asks for these lines to be reversed, I'm having problems - and therefore ask for help - with the input).
So far, I have this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENGTH 1024
int main(int argc, char *argv[]){
char* input[LENGTH];
if(argc==2){
FILE *fp = fopen(argv[1], "rt");
if(fp!=NULL){
int i=0;
while(fgets(input, sizeof(input), fp)!=NULL){
input[i] = (char*)malloc(sizeof(char) * (LENGTH));
fgets(input, sizeof(input), fp);
i++;
}
printf("%s", *input);
free(input);
}
else{
printf("File opening unsuccessful!");
}
}
else{
printf("Enter an argument.");
}
return 0;
}
I also have to check whether or not memory allocation has failed. This program in its' current form returns nothing when run from the command line.
EDIT: I think it's important to mention that I get a number of warnings:
passing argument 1 of 'fgets' from incompatible pointer type [-Wincompatible-pointer-types]|
attempt to free a non-heap object 'input' [-Wfree-nonheap-object]|
EDIT 2:
Example of input:
These
are
strings
... and the expected output:
esehT
era
sgnirts
In the exercise, it's specified that the maximum length of a line is 1024 characters.
You probably want something like this.
Comments are in the code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENGTH 1024
int main(int argc, char* argv[]) {
if (argc == 2) {
FILE* fp = fopen(argv[1], "rt");
if (fp != NULL) {
char** lines = NULL; // pointer to pointers to lines read
int nboflines = 0; // total number of lines read
char input[LENGTH]; // temporary input buffer
while (fgets(input, sizeof(input), fp) != NULL) {
char* newline = malloc(strlen(input) + 1); // allocate memory for line (+1 for null terminator)
strcpy(newline, input); // copy line just read
newline[strcspn(newline, "\n")] = 0; // remove \n if any
nboflines++; // one more line
lines = realloc(lines, nboflines * sizeof(char*)); // reallocate memory for one more line
lines[nboflines - 1] = newline; // store the pointer to the line
}
fclose(fp);
for (int i = 0; i < nboflines; i++) // print the lins we've read
{
printf("%s\n", lines[i]);
}
}
else {
printf("File opening unsuccessful!");
}
}
else {
printf("Enter an argument.");
}
return 0;
}
Explanation about removing the \n left by fgets: Removing trailing newline character from fgets() input
Disclaimers:
there is no error checking for the memory allocation functions
memory is not freed. This is left as an exercise.
the way realloc is used here is not very efficient.
you still need to write the code that reverses each line and displays it.
You probably should decompose this into different functions:
a function that reads the file and returns the pointer to the lines and the number of lines read,
a function that displays the lines read
a function that reverses one line (to be written)
a function that reverses all lines (to be written)
This is left as an exercise.

How can I delete extra break line when read txt in C

I'm new in C and try to do some practice
I want to change the txt file from
Chicken
10000
Cow
20000
Duck
20
Sheep
1000
to
Chicken 10000
Cow 20000
Duck 20
Sheep 1000
then destroy the animal <50
Chicken 10000
Cow 20000
Sheep 1000
My first step:
Read the file and compose the letter to the string.
Like the first word "Chicken", will be composed of "C" "h" "i" "c" "k" "e" "n".
As following my code, when I use strcpy(str0, ""); I have changed the string array strings[0] = str0; (str0 is "Chicken" now) before strcpy(str0, "");, but when strcpy(str0, "");operate, my memory in strings[0] was also be changed.
How can I fix the problem?
This is my code:
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
int main() {
char str0[256] = "";
char tmp_char;
const char *string[2];
int i, c, line_counter=0;
FILE *file;
file = fopen("cry.txt", "r");
if (file) {
while ((c=getc(file)) !=EOF) {
if (c == 10) {
line_counter++;
string[0]=str0;
strcpy(str0, "");
continue;
}
tmp_char = c;
append(str0, tmp_char);
}
fclose(file);
}
return 0;
}
You should divide your problem into smaller pieces and implement them independently from each other --> "divide and conquer"
Before starting programming you should think about the steps.
I would analyze the problem the following way:
open infile
open outfile
while not eof
read data set --> 2 lines
read a line -> parse animal name
read a line -> parse number
filter data set
write data set
close files
I would derive the following structures/functions from this (or use library functions - depending on the class's task):
structure
DataSet{animalName, count};
function
readLine(filehandle, bufferpointer, maxbuffersize) -> success
readDataset(bufferpointer1, bufferpointer2) -> success
(parseAnimalName(linebuffer1, buffersize, namebuffer, maxlength) -> success)
(parseAnimalCount(linebuffer, numberpinter) -> success)
filterAnimal(DataSet) -> bool
writeAnimal(filehandle, DataSet) --> success
Depending on the possibility to use libraries parse functions I would omit the functions in parentheses.
With this isolated little functionalities it should be a lot easier to implement the whole problem and also analyze where bugs occur.
Once you solve the problem yourself you can compare it with my solution. I commented it pretty heavily.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LIMIT 30
// Arbitrary max number of items
#define MAX_ITEMS 16
// Arbitrary maximum result size
#define MAX_RESULT_SIZE 256
// Output string must keep both animal name and stringified integer.
// This integer will take at most 11 characters.
// It means that in string of format "%s %d\n" the animal name
// must take at most (MAX_RESULT_SIZE - 11 - whitespace - \n - NUL) characters.
#define MAX_STR_SIZE ((MAX_RESULT_SIZE) - 14)
int main(void) {
int retcode;
const char *filename = "file.txt";
FILE *file = fopen("file.txt", "r");
if (file == NULL) {
fprintf(stderr, "Failed to open file %s: %s", filename, strerror(errno));
}
char text[MAX_STR_SIZE + 1];
int number;
int id = 0;
char results[MAX_ITEMS][MAX_RESULT_SIZE];
// Dynamically define fmt string to limit fscanf to MAX_STR_SIZE
// Format specifier "%256s" makes sure that fscanf won't read a string that is
// longer than 256 characters (remember about additional one byte for NUL character,
// output memory must have space for 257 characters).
char fmt[32];
snprintf(fmt, sizeof(fmt), "%%%zus\n", (size_t)MAX_STR_SIZE);
while(1) {
if (id >= MAX_ITEMS) break;
retcode = fscanf(file, fmt, text);
if (retcode == EOF) break;
// From fscanf manual page we know 'On success, these functions return the
// number of input items successfully matched and assigned'. If this is
// different than 1 then something went wrong with input string. Maybe
// It's different than we assumed.
if (retcode != 1) {
fprintf(stderr, "Input is not matching format specifiers");
exit(EXIT_FAILURE);
}
retcode = fscanf(file, "%d\n", &number);
if (retcode == EOF) break;
if (retcode != 1) {
fprintf(stderr, "Input is not matching format specifiers");
exit(EXIT_FAILURE);
}
// Filtering logic
if (number < LIMIT) continue;
sprintf(results[id++], "%.*s %d", MAX_STR_SIZE, text, number);
}
for(int i = 0; i < id; i++) printf("%s\n", results[i]);
fclose(file);
return 0;
}
your line just assigns pointer to the variable str0 into string[0]
string[0]=str0;
That is why your string[0] changes after str0 changes. They point to the same memory.
To solve this, you have to copy value from str0 into string[0]

Parsing contents of a textfile in C(Deleting parts, storing others)

I have a basic .txt file that may contain an unknown amount of pieces of data exactly in this format and I need to extract the second part after the '=' identifier. For example:
variable1=Hello
variable2=How
variable3=Are
variable4=You?
I need to extract "Hello" "How" "Are" and "You?" separately and store them into an array(removing/ignoring the variable name) and being able to call each word individually. I'm doing this in C and here is what I currently have.
#include <stdio.h>
#include <string.h>
int main()
{
char*result;
char copy[256];
FILE * filePtr;
filePtr = fopen("testfile.txt", "r+");
strcpy(copy, "testfile.txt");
while(fgets(copy, 256, filePtr)!= NULL)
{
result = strchr(copy, '=');
result = strtok(NULL, "=");
printf("%s",result);
if(result != 0)
{
*result = 0;
}
result = strtok(copy, "=");
}
return 0;
}
My current output is
(null)How
Are
You?
You do not need strtok, using strchr is enough.
no need to copy the filename to the copy buffer.
probably not necessary to open the file in update mode "%r+" either.
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *words[20];
int n = 0;
char *result;
char copy[256];
FILE *filePtr;
filePtr = fopen("testfile.txt", "r");
while (fgets(copy, 256, filePtr) != NULL) {
copy[strcspn(copy, "\n")] = '\0'; /* strip the \n if present */
result = strchr(copy, '=');
if (result != NULL) {
words[n++] = strdup(result + 1);
printf("%s ", result + 1);
}
}
printf("\n");
fclose(filePtr);
return 0;
}
Note the one liner to strip the trailing \n left at the end of copy by fgets(): copy[strcspn(copy, "\n")] = '\0';. It works even if fgets() did not see a \n before the end of the buffer or before the end of file. strcspn counts returns the number of characters in copy that are not in the second argument, thus it returns the length of the line without the \n.
The words are collected into an array words of pointers to strings. Each word is copied into memory allocated by malloc by the strdup function. strdup is not part of Standard C, but part of Posix and probably present in your environment, possibly written as _strdup.
Note also that you should also test for failure to open the file, failure to allocate memory in strdup, and also handle more than 20 strings...
If there is a fixed set of words and you just want to strip the initial parts, you can use a simpler hardcoded approach:
int main(void) {
char word1[20], word2[20], word3[20], word4[20];
FILE *filePtr;
filePtr = fopen("testfile.txt", "r");
if (fscanf(filePtr,
"%*[^=]=%19[^\n]%*[^=]=%19[^\n]%*[^=]=%19[^\n]%*[^=]=%19[^\n]",
word1, word2, word3, word4) == 4) {
printf("%s %s %s %s\n", word1, word2, word3, word4);
// perform whatever task with the arrays
} else {
printf("parse failed\n");
}
fclose(filePtr);
return 0;
}

How to read in a text file of tab-separated integers in C?

I have a file of simply tab-separated integers (a .txt file) and I wish to read them in with just C, line by line. So, say each line has 5 integers. How can I accomplish this?
My first attempt was as follows. It was just to read in a single integer, but even that didn't work:
FILE *fp;
char blah[255];
int *some_int;
fp = fopen("test.txt", "rt");
while (fgets(blah, 255, fp) != NULL)
{
sscanf(blah, "%d", some_int);
printf("%d\n", *some_int);
}
Here's a way no one else suggested, that doesn't use fscanf so you can have sane error handling:
char buffer[BUFSIZE];
size_t size = 5;
int *data = malloc(size * sizeof *line);
if(line == NULL) error();
while(fgets(buffer, sizeof buffer, fp)
{
size_t i = 0;
char *next = buffer;
while(*next && *next != '\n')
{
data[i++] = strtol(next, &next, 0);
// check for errors
}
}
Basically, instead of trying to use *scanf's "%d" to read characters, use the function it (probably) calls to do the conversion: strtol. Where *scanf goes through the string to match the format string but doesn't let you "save your place" in between function calls, strtol does, which is what you need to read an arbitrary number of integers.
I haven't written all your code for you - you have to do the hard error handling. Possible errors include:
i == size, in which case you can try to make data bigger with realloc. Alternately, you could loop through the buffer and count how many numbers there are beforehand, then allocate that many so you don't need to reallocate later.
fgets didn't read the entire line (check that the last character before '\0' is '\n'). In this case you'll probably want to refill the buffer and keep reading numbers. Be careful in this case - you'll likely need to go back and recalculate the last number - fgets might have cut it off. (This is one disadvantage to using fgets.)
Erroneous input - handle however you like.
#include <stdio.h>
int main(){
FILE *fp;
int scanned = 0;
int some_ints[5];
fp = fopen("test.txt", "r");
while ((scanned = fscanf(fp, "%d %d %d %d %d", some_ints, some_ints+1, some_ints+2, some_ints+3, some_ints+4)) != EOF) {
if(scanned ==5){
printf("%d %d %d %d %d\n", some_ints[0], some_ints[1], some_ints[2], some_ints[3], some_ints[4]);
}
else {
printf("Whoops! Input format is incorrect!\n");
break;
}
}
}
I'd do something like this:
int storedVals[MAX_STORED_VALS];
int bf;
int ii=0;
while (!feof(fp) && ii<MAX_STORED_VALS) {
if (fscanf(fp," %d",&bf)) {
storedVals[ii++]=bf;
}
}
fscanf automatically does white space trimming. So as long as there's a space in your scan string, it'll get rid of zero or more \t (tabs) and \n (newlines) to find the next integer. Of course, this doesn't do much by way of error correction.

Resources