Program works with string literals but not with string arrays - c

I have a hashtable ADT which has two functions, insert and lookup. I put in to the insert function a hash table, hash table size, ID #, and book title and that inserts it into the hash table. This works fine when I pass it a string literal, i.e. insert(...,"Hello, world!"...); It doesn't work when I read in strings from a file, store them in an array, and try and use my insert and lookup functions.
I have all of my code here but the most important files are main.c and hash.c. Hash.c has the newHash(), hash(), insert(), and lookup() functions and main.c reads from two files, in this case test1.lib.in and test1.req.in, and from the first file will get the library id and title of a book from each line and then put it in the hash table. From the second file, it gets requests for a book title and should print the ids in its linked list.
List of links to files https://docs.google.com/document/d/1tFNs-eVkfnCfjwAHcAUdHtUl1KVv_WcnW2IS0SRFvcM/edit?usp=sharing
Example of code that works.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "list.h"
#include "hash.h"
int main(){
ListHndl* temp = newHash(10);
insert(442440, "cvyaqbznxel", 10,temp);
lookup(temp,"cvyaqbznxel", 10);
return 0;
}
Code that doesn't work
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "list.h"
#include "hash.h"
int main(int argc, char * argv[]) {
if (argc != 3) {
printf("Incorrect arguments, please specify 2 files to be read\n");
return EXIT_FAILURE;
}
FILE *file = fopen( argv[1], "r");
FILE *secondFile = fopen(argv[2], "r");
if (file == 0 || secondFile == 0) {
printf("Could not open a file\n");
return EXIT_FAILURE;
}
int numDataLines2;
int numDataLines;
int hashTableSize;
//First line of first file gives number of lines in file and
//size of hash table to be made
if(fscanf(file, "%d%d", &numDataLines, &hashTableSize) < 2) {
printf("Unable to parse first line of first file\n");
return EXIT_FAILURE;
}
ListHndl* theHash = newHash(hashTableSize);
int libraryID;
char *tempString = calloc(numDataLines,41*sizeof(char));
char lineHolder[129];
//discard the new line which always shows up
fgets(lineHolder, 128, file);
for(int i = 0; i < numDataLines; i++) {
//Gets the whole line to be scanned with sscanf
fgets(lineHolder, 128, file);
//If the line consists of just a newline char, continue
if(strcmp(lineHolder, "\n") == 0 ) {
continue;
}
//Scans the line retrieved from fgets and placed in lineHolder
if(sscanf(lineHolder, "%d, %40[^\n]", &libraryID,&tempString[i]) == 0){
printf("Unable to parse line %d of first file\n",i+2);
return EXIT_FAILURE;
}
insert(libraryID, &tempString[i], hashTableSize, theHash);
}
char String[41];
fgets(String, 40, secondFile);
numDataLines2 = atoi(String);
char *storeSecondFileStuff = calloc(numDataLines2,41*sizeof(char));
for(int i = 0; i< numDataLines2; i++) {
fgets(lineHolder, 128, secondFile);
if(strcmp(lineHolder, "\n") == 0) {
continue;
}
if(sscanf(lineHolder, "%40[^\n]",&storeSecondFileStuff[i]) == 0) {
printf("Unable to parse line %d of second file\n",i+2);
return EXIT_FAILURE;
}
lookup(theHash, &storeSecondFileStuff[i], hashTableSize);
}
printf("\n");
fclose(file);
fclose(secondFile);
return 0;
}
Thanks!

I think you have multiple problems. To start with, you might not be scanning your input line correctly. Change your line
if(sscanf(lineHolder, "%d, %40[^\n]", &libraryID,&tempString[i]) == 0)
to
if(sscanf(lineHolder, "%d, %40[^\n]", &libraryID, tempString) < 0)
that way, you will trap the situation where the sscanf function did not successfully convert both arguments - for example, if there is no comma in the input line. Note that sscanf returns the number of successful conversions; success would return a value of 2, so testing for <2 is the right way to go.
Note also that I changed &tempString[i] to tempString. The former points to some place along tempString - which only has 41 characters allocated to it. Yet you always allow up to 40 characters (plus '\0' to be written to it - so you will write past the end of the string. Since this is only a temporary variable, there is no sense in doing this. Just scan the input into the temp variable, then do whatever you need to do with it.
This means that your insert also changes, from
insert(libraryID, &tempString[i], hashTableSize, theHash);
to
insert(libraryID, tempString, hashTableSize, theHash);
Again, you need to do the same thing lower down in your code.
Here is an attempt at making the code work for you - see if this hits the spot. Note that all I really did was change the type of tempString and storeSecondFileStuff, and modified the way they were used in various function calls accordingly. I did not attempt to compile / run because of the complexity of the other files involved - but this should help a bit:
int main(int argc, char * argv[]) {
if (argc != 3) {
printf("Incorrect arguments, please specify 2 files to be read\n");
return EXIT_FAILURE;
}
FILE *file = fopen( argv[1], "r");
FILE *secondFile = fopen(argv[2], "r");
if (file == 0 || secondFile == 0) {
printf("Could not open a file\n");
return EXIT_FAILURE;
}
int numDataLines2;
int numDataLines;
int hashTableSize;
//First line of first file gives number of lines in file and
//size of hash table to be made
if(fscanf(file, "%d%d", &numDataLines, &hashTableSize) < 2) {
printf("Unable to parse first line of first file\n");
return EXIT_FAILURE;
}
ListHndl* theHash = newHash(hashTableSize);
int libraryID;
char **tempString = calloc(numDataLines,sizeof(char*)); // <<< ARRAY of pointers
char lineHolder[129];
//discard the new line which always shows up
fgets(lineHolder, 128, file);
for(int i = 0; i < numDataLines; i++) {
//Gets the whole line to be scanned with sscanf
fgets(lineHolder, 128, file);
tempString[i] = calloc(1, 41 * sizeof(char)); // <<< space for this string
//If the line consists of just a newline char, continue
if(strcmp(lineHolder, "\n") == 0 ) {
continue;
}
//Scans the line retrieved from fgets and placed in lineHolder
if(sscanf(lineHolder, "%d, %40[^\n]", &libraryID, tempString[i]) < 0){ // <<< changed
printf("Unable to parse line %d of first file\n",i+2);
return EXIT_FAILURE;
}
insert(libraryID, tempString[i], hashTableSize, theHash); // <<< changed
}
char String[41];
fgets(String, 40, secondFile);
numDataLines2 = atoi(String);
char **storeSecondFileStuff = calloc(numDataLines2, sizeof(char*)); // changed: again char **
for(int i = 0; i< numDataLines2; i++) {
fgets(lineHolder, 128, secondFile);
storeSecondFileStuff[i] = calloc(1, 41 * sizeof(char));
if(strcmp(lineHolder, "\n") == 0) {
continue;
}
if(sscanf(lineHolder, "%40[^\n]",storeSecondFileStuff[i]) == 0) {
printf("Unable to parse line %d of second file\n",i+2);
return EXIT_FAILURE;
}
lookup(theHash, storeSecondFileStuff[i], hashTableSize); // <<<< changed
}
printf("\n");
fclose(file);
fclose(secondFile);
return 0;
}

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

C: How to read a text file and grab certain values after a certain point?

So basically the text file would look like this
Starting Cash: 1500
Turn Limit (-1 for no turn limit): 10
Number of Players Left To End Game: 1
Property Set Multiplier: 2
Number of Houses Before Hotels: 4
Must Build Houses Evenly: Yes
Put Money In Free Parking: No
Auction Properties: No
Salary Multiplier For Landing On Go: 1
All I need from the file is basically anything after ":"
I'm just confused how to only read anything after a ":"?
This is what I have right now. I just can't seem to think of a way to only scan for the numbers/yesorno.
void readRules(char*file_name)
{
Rules r;
FILE *file = NULL;
file = fopen(file_name, "r");
if (file == NULL) {
printf("Could not open %s\n", file_name);
return;
}
char c=fgetc(file);
fscanf(file, "%c", &c);
while (!feof(file))
{
fscanf(file, "%c", &c);
if(c==':')
{
r.startCash=c;
}
}
printf("There are %c word(s).\n", r.startCash);
fclose(file);
}
Thank you.
This program will read integers following a colon in each line of the file given. I imagine this is appropriate? You also have some strings after colons. If you want to read those, you can try scanning for a string "%s" and testing if the function returns nonzero (for at least one format pattern matched).
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 1000
void readRules (const char *filename) {
FILE *fp;
char *lp, line[MAXLINE];
int n;
// Return early if file cannot be opened.
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "Error: Couldn't open \"%s\"!\n", filename);
return;
}
// Use fgets to read consecutive lines. Returns NULL on error or EOF.
while (fgets(line, MAXLINE, fp) != NULL) {
// Read until newline is hit or buffer size exceeded.
for (lp = line; *lp != '\n' && (lp - line) < MAXLINE; lp++) {
// If encounter colon and sccanf reads at least 1 integer..
if (*lp == ':' && sscanf(lp + 1, "%d", &n) == 1) {
fprintf(stdout, "%d\n", n);
break;
}
}
}
// Clean up.
fclose(fp);
}
int main (int argc, const char *argv[]) {
readRules("test.txt");
return 0;
}
When run with your example input, it produces:
1500
10
1
2
4
1

how to read specific lines of a text document and write them to another text | C

I have created a function that takes as a parameter the name of a source file, the name of a destination file and the beginning and end lines of the source file lines that will be copied to the destination file, like the example below. All I want to do is to input the lines that I want to copy to the other text file like the example below:
The code I show you just "reads" the content of the one text file and "writes" another one. I want to "write" specific lines that the user gives, not the whole text file
Inputs by the user:
Source_file.txt //the file that the destination file will read from
destination_file.txt //the new file that the program has written
2 3 // the lines that it will print to the destination file: 2-3
Source_file.txt:
1
2
3
4
5
6
destination_file.txt
2
3
code:
#include <stdio.h>
#include <stdlib.h>
void cp(char source_file[], char destination_file[], int lines_copy) {
char ch;
FILE *source, *destination;
source = fopen(source_file, "r");
if (source == NULL) {
printf("File name not found, make sure the source file exists and is ending at .txt\n");
exit(EXIT_FAILURE);
}
destination = fopen(destination_file, "w");
if (destination == NULL) {
fclose(source);
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
while ((ch = fgetc(source)) != EOF)
fputc(ch, destination);
printf("Copied lines %d from %s to %s \n",
lines_copy, source_file, destination_file, ".txt");
fclose(source);
fclose(destination);
}
int main() {
char s[20];
char d[20];
int lines;
printf("-Enter the name of the source file ending in .txt\n"
"-Enter the name of the destination file ending in .txt\n"
"-Enter the number of lines you want to copy\n\n");
printf(">subcopy.o ");
gets(s);
printf("destination file-> ");
gets(d);
printf("Lines: ");
scanf("%d", &lines);
cp(s, d, lines);
return 0;
}
In cp(), in order to select the lines to keep, you have to know their position in the input-file. Thus, you need to count lines.
Using fgets instead of fgetc will allow you to count the lines.
On the other hand, if I wanted to select lines 3 and 7 to 12 in a file, I'd use:
sed -n -e "3p;7,12p" < input.txt > output.txt
this is a very simple solution, let's say you know that the maximun length of a line will be 100 characters for simplicity (if a line is longer than 100 characters only the first 100 will be taken)
at the top (outside main) you can write
#ifndef MAX_LINE_SIZE
#define MAX_LINE_SIZE 100
#endif
i know many people don't like this but i think in this case it makes the code more elegant and easier to change if you need to modify the maximum line size.
to print only the wanted lines you can do something like this
char line[MAX_LINE_SIZE];
int count = 0;
while (fgets(line, MAX_LINE_SIZE, source)){
count++;
if (3 <= count && count <= 5){
fputs(line, destination);
}
}
The while loop will end when EOF is reched because fgets returns NULL.
P.S. there could be some slight errors here and there since i wrote it pretty fast and going by memory but in general it should work.
There are some problems in your program:
Do not use gets(), it may cause buffer overflows.
Always use type int to store the return value of fgetc() in order to distinguish EOF from regular byte values.
You pass an extra argument ".txt" to printf(). It will be ignored but should be removed nonetheless.
To copy a range of lines from source to destination, you can just modify your function this way:
#include <stdio.h>
#include <string.h>
#include <errno.h>
void cp(char source_file[], char destination_file[], int start_line, int end_line) {
int ch;
int line = 1, lines_copied;
FILE *source, *destination;
source = fopen(source_file, "r");
if (source == NULL) {
printf("Cannot open input file %s: %s\n",
source_file, strerror(errno));
exit(EXIT_FAILURE);
}
destination = fopen(destination_file, "w");
if (destination == NULL) {
printf("Cannot open output file %s: %s\n",
destination_file, strerror(errno));
fclose(source);
exit(EXIT_FAILURE);
}
while ((ch = fgetc(source)) != EOF) {
if (line >= start_line && line <= end_line) {
fputc(ch, destination);
}
if (ch == '\n') {
line++;
}
}
lines_copied = 0;
if (line > start_line) {
if (line >= end_line) {
lines_copied = end_line - start_line + 1;
} else {
lines_copied = line - start_line + 1;
}
}
printf("Copied lines %d from %s to %s\n",
lines_copy, source_file, destination_file);
fclose(source);
fclose(destination);
}
int main() {
char source_file[80];
char destination_file[80];
int start_line, end_line;
printf("-Enter the name of the source file ending in .txt\n"
"-Enter the name of the destination file ending in .txt\n"
"-Enter the start and end line\n\n");
printf(">subcopy.o ");
if (scanf("%79s", source_file) != 1) {
return 1;
}
printf("destination file-> ");
if (scanf("%79s", destination_file) != 1) {
return 1;
}
printf("Start and end lines: ");
if (scanf("%d %d", &start_line, &end_line) != 2) {
return 1;
}
cp(source_file, destination_file, start_line, end_line);
return 0;
}

My program not work as expected

I need to find the position of some strings. These strings are stored in a file named queryfile , from an other file named datafile.
However, my program does not work as expected.
Can some one help me?
My program
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *queryfile;
queryfile = fopen("op2query.txt","r");
FILE *datafile;
datafile = fopen("op2data.txt","r" );
int i = 1;
char word[99];
char search[99];
if(queryfile==NULL) {
printf("Error in reading Query File");
exit(1);
}
if(datafile==NULL) {
printf("Error in reading Data File");
exit(1);
}
while(fscanf(queryfile,"%98s",search)==1){
while(fscanf(datafile,"%98s",word)==1){
if (strcmp(word,search)==0){
printf("\n %i %s ", i, search);
rewind(datafile);
i=1;
break;
}
else
i++;
}
}
fclose(datafile);
fclose(queryfile);
return 0;
}
I build an array of each set of words to be tested, by splitting the query string into words. These words can span a line break in the data file. I mark the data file position on the second word of the set, if the search fails I seek to that point (if necessary). The program succeeds even if I duplicate every word "age" in the data file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXWORDS 5
#define MAXLEN 99
int main()
{
int j, i, done, words, count;
long mark;
char word[MAXLEN];
char search[MAXLEN];
char *tok, *sptr[MAXWORDS];
FILE *queryfile;
FILE *datafile;
if ((queryfile = fopen("op2query.txt","r")) == NULL) {
printf("Error in reading Query File");
exit(1);
}
if ((datafile = fopen("op2data.txt","r" )) == NULL) {
printf("Error in reading Data File");
exit(1);
}
while(fgets(search, MAXLEN, queryfile) != NULL){
words = 0;
done = 0;
count = 0;
mark = -1;
tok = strtok(search, " \r\n");
while (tok && words < MAXWORDS) { // build array of query
sptr[words++] = tok;
tok = strtok(NULL, " \r\n"); // strips newline too
}
if (words < 1) // no more queries
break;
rewind(datafile); // beginning of file
while (!done) { // until none to read
count++;
if (mark >= 0) // when more than one word to search
fseek (datafile, mark, SEEK_SET);
mark = -1;
for (j=0; j<words; j++) {
if (j == 1) // mark for next search
mark = ftell(datafile);
if (fscanf(datafile, "%98s", word) != 1){
done = 1; // end of file
break;
}
if (strcmp(sptr[j], word)!=0)
break; // failed multi word search
}
if (done)
printf("NOT FOUND!");
else if (j == words) { // if all words found
printf("%d", count);
done = 1; // success
}
}
for (i=0; i<words; i++)
printf(" %s", sptr[i]); // show array of words asked
printf("\n");
}
fclose(datafile);
fclose(queryfile);
return 0;
}
Program output:
18 wisdom
40 season
NOT FOUND! summer
22 age of foolishness
UPDATE - I print NOT FOUND! when query not found. Added "summer" to query file.
you should put some debug-output behind the fscanf-calls (like printf("search:<%s> word:<%s>", search, word);
Then you will see, that fscanf stops at finding a white-space. you compare wisdom to each consecutive word in op2data.txt.
You should read line by line with fgets() removing the CR/LF from search.
But be aware, that the multi-word-search-word in data-file may be split between lines. like:
find me
i am the text to find
me in this file
so a better solution would be:
read search word by line (remove CR/LF) (normalize it by removing double spaces and not-letters)
read a chunk from datafile and normalize it too.
compare or continue by moving the read-position in data left by length of length of search word

Word palindrome in C

My task is to find word palindromes in a text file and to NOT print them into results file. The results file should only contain all the spaces and words that are NOT palindromes. I've been working on this program for two solid weeks, but as I am a total newb in C, I can't simply imagine how to do this correctly. Also, I have to work in Linux environent, so I can't use commands like strrev() which would make my life a lot easier at this point...
Anyways, data file contains a lot of words in a lot of lines separated by quite a few spaces.
Here is the program that is working, but doesn't work with any spaces, because I don't know how to check them at the needed place.
#include <stdio.h>
#include <string.h>
const int CMAX = 1000;
const int Dydis = 256;
FILE *dataFile;
FILE *resFile;
void palindrome(char *linex);
int main(){
char duom[CMAX], res[CMAX], linex[Dydis];
printf("What's the name of data file? \n");
scanf("%s", duom);
dataFile=fopen(duom, "r");
if (dataFile==NULL){
printf ("Error opening data file \n");
return 0;
};
printf("What's the name of results file? \n");
scanf ("%s", res);
resFile=fopen(res, "w");
if (resFile==NULL){
printf ("Error opening results file \n");
return 0;
};
while (fgets(linex, sizeof(linex), dataFile)) {
palindrome(linex);
}
printf ("all done!");
fclose(dataFile);
fclose(resFile);
}
void palindrome(char *linex){
int i, wordlenght, j;
j = 0;
char *wordie;
const char space[2] = " ";
wordie = strtok(linex, space);
while ( wordie != NULL ) {
wordlenght = strlen(wordie);
if (wordie[j] == wordie[wordlenght-1]) {
for (i = 0; i < strlen(wordie); i++) {
if (wordie[i] == wordie[wordlenght-1]) {
if (i == strlen(wordie)-1) {
fprintf(resFile,"");
}
wordlenght--;
}
else {
fprintf(resFile,"%s", wordie);
break;
}
}
}
else {
fprintf(resFile,"%s", wordie);
}
wordie = strtok(NULL, space);
}
}
EDIT:
Code below works as following:
input file is read char by char
if char read isn't alphanumeric, then it is written to the output file
else, the whole word is read with fscanf
if word is not a palindrome, then write to the output file
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int is_pal(char* word) {
size_t len = strlen(word);
char* begin = word;
char* end = word + len - 1;
if (len == 1) {
return 1;
}
while (begin <= end) {
if (*begin != *end) {
return 0;
}
begin++;
end--;
}
return 1;
}
int main(void)
{
FILE* fin = fopen("pals.txt", "r");
if (fin == NULL) {
perror("fopen");
exit(1);
}
FILE* fout = fopen("out_pals.txt", "w");
if (fout == NULL) {
perror("fopen");
exit(1);
}
int ret;
char word[100];
while ((ret = fgetc(fin)) != EOF) {
if (!isalpha(ret)) {
fprintf(fout, "%c", ret);
}
else {
ungetc(ret, fin);
fscanf(fin, "%s", word);
if (!is_pal(word)) {
fprintf(fout, "%s", word);
}
}
}
fclose(fin);
fclose(fout);
return 0;
}
I've created file with following content:
cancer kajak anna sam truck
test1 abc abdcgf groove void
xyz annabelle ponton belowoleb thing
cooc ringnir
The output file :
cancer sam truck
test1 abc abdcgf groove void
xyz annabelle ponton thing
(line with two spaces)
As you can see, the number of spaces between words are the same as in the input file.
I've assumed that single word could have 100 chars maximum. If there would be longer words, reading with fscanf onto fixed-size buffer can be harmful.
Hints:
strtok() gives you a pointer to the start of delimited words but it does not
extract them or put them in their own string for you.
You need some logic to find the end of each word. The function
strlen() will tell you how many characters there are from the char*
that it gets until a null-character. If you give it a pointer to the start
of a word within a sentence it will give you the length from the start of the
word to the end of the sentence.
Breaking palindrome() into a function that loops over words in a line and a
function that returns whether or not a single word is a palindrome
may help.
Your for loop is checking each pair of letters twice. i only needs to scan over half
of the word length.
You only need a single if within palindrome(). I'm not sure why you have so many.
They're redundant.

Resources