I want to read the words from a text file into an array.
Why does this code work with a 2D array (a[50][50]) but not with a 1D array (a[50])?
This code prints what I want but it also print some other useless characters. What causes this?
void inputwords(){
int i=0;
char wrd[50];
FILE * fptr;
char fname[20]="txt.file";
fptr=fopen(fname,"w");
if(fptr==NULL) {
printf("error in opening file!");
exit(1);
}
while(wrd!='\0'){
fgets(wrd,sizeof wrd,stdin);
fprintf(fptr,"%s",wrd);
if(wrd[i]=='*' && wrd[i+1]=='*' && wrd[i+2]=='*' && wrd[i+3]=='*' &&
wrd[i+4]=='T' && wrd[i+5]=='E' && wrd[i+6]=='L' && wrd[i+7]=='O' &&
wrd[i+8]=='S') {
break;
}
}
fclose(fptr);
return;
}
void readfile(){
FILE *fptr;
char a[50][50];
int i=0;
char fname[20]="txt.file";
fptr=fopen(fname,"r");
while(fgets(a[i],50,fptr)){
i++;
}
for(i=0;i<50;i++){
printf("%s",a[i]);
}
fclose(fptr);
return;
};
main(){
inputwords();
readfile();
return(0);
}
for(i=0;i<50;i++){
printf("%s",a[i]);
}
This prints out the value of every pointer in a[50]. Once you reach past the char pointers which are actually set to point to something, you're just printing out the value of the pointer itself.
for(int n=0; n<i; n++){
printf("%s",a[n]);
}
Would work.
I just tested the answer of Cowbolt, it works , and also wanted to ask you why do you have the line in inputwords() :
while(wrd!='\0') {
The condition of null character will never happen from user input. It is better to have clear instructions and say :
printf("Enter text (to finish input, type on a line of its own:****TELOS ):");
while (1) {
/*be aware that your final i marks the position of string "****TELOS" */
/* so if you dont want it to output, have the n<i-1 in Cowbolt solution*/
The below program giving the following error when compiling:
./vpl_test: line 2: 18699 Segmentation fault (core dumped) ./solution
What could be the problem with the below C program ?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void sort(long *sorted, int count,long value){
int i=0;
sorted[count] = value;
if(count == 0)return;
for(i=count;i>=0;i--){
if(value<sorted[i-1])
sorted[i] = sorted[i-1];
else break;
}
sorted[i]=value;
}
int main(int argc,char *argv[]){
FILE *fp = NULL;
long sorted[1024];
long value;
int count = 0;
int i=0;
fp = fopen("brandlist.txt","r+");
//fp = fopen("brandlist.txt","w");
if(NULL == fp){
perror("fopen");
exit(0);
}
while(!feof(fp)){
fscanf(fp,"%ld\n",&sorted[i]);
sort(sorted,count,value);
++count;
}
for(i=0;i<count;i++){
fprintf(fp,"%ld\n",sorted[i]);
}
if(fp){
fclose(fp);
fp = NULL;
}
}
I could not reproduce the segfault (probably because of being "lucky" or maybe because of having wrong input).
The problem I did have was wrong sorting and strange values in sorted output, I believe that the same problem causes all misbehaviours, including the segfault in your case.
Here is a commented version of your code, picking up from the excellent comments and adding the (many) necessary changes to work on strings instead of integers.
(Allow me this little rant: It would really have saved a lot of time to provide actual sample input from start.)
It does have no segfault (at least not for me), no missorting and no strange values.
Output (i.e. new content of input file):
Damro
Duriyan
Evoks
Godrej
Luxxe
Nilkamal
Wipro
Zuari
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef char brandname[20];
void sort(brandname *sorted, int count, brandname *value){
int i=0;
strncpy((char*)sorted[count], (char*)value, sizeof(brandname));
if(count == 0) return;
// picking up input by BLUEPIXY;
// this probably prevents the segfault,
// it definitly prevents strange values
// appearing in the sorted result
for(i=count;i>0;i--)
{
if(0>strncmp((char*)value, (char*)sorted[i-1],sizeof(brandname)))
strncpy( (char*)sorted[i], (char*)sorted[i-1], sizeof(brandname));
else break;
}
strncpy((char*)sorted[i], (char*)value, sizeof(brandname));
}
int main(int argc,char *argv[]){
FILE *fp = NULL;
brandname sorted[1024];
brandname value;
int count = 0;
int i=0;
fp = fopen("brandlist.txt","r+");
//fp = fopen("brandlist.txt","w");
if(NULL == fp){
perror("fopen");
exit(0);
}
// picking up input from cooments on feof
// but also use the increasing "count"
// instead of unchanging "i"
while(1==fscanf(fp,"%s", value))
{
// use the read value inside "sorted[count]"
sort(sorted, count, &value);
++count;
}
// do not append sorted to input
rewind(fp);
for(i=0;i<count;i++){
fprintf(fp,"%s\n",sorted[i]);
}
if(fp){
fclose(fp);
fp = NULL;
}
// avoid a warning
return 0;
}
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.
I have a script in C that reads a file structured in lines like this:
1,example,2,3;
2,exampl,3,5;
3,examp,7,4;
4,exam,9,1;
And the script is here:
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
fscanf(fptr,"%d,%[^/,],%d,%s;", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon);
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
The problem I have is, that it reads only even lines of the file (2nd, 4th, 6th, 8th)...
How should I edit the code so it would read all lines?
Thanks for any help.
UPDATE1:
void nacti(emp *p,int n)
{
FILE *fptr;
fptr=fopen("ulozka.txt","r");
if(fptr==NULL){
printf("Error opening file!");
getchar();
}
typedef struct
{
int id;
char nojm[32];
int salar;
char phon[32];
} data_t;
int i = 0;
data_t m[4];
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
printf("%d,%s,%d,%s\n", m[4].id,m[4].nojm,m[4].salar,m[4].phon);
//printf("%d",pocet);
}
If there is only m[4], the code will only read 4 lines of the file? How should I edit it to read "indefinit" number of lines?
Your code should be replaced with the following:
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
The fscanf call in the while loop condition will be executed every loop iteration, so you don't need to call it again inside the loop.
UPDATE:
The following solution works for me. You can try it here.
#include <stdio.h>
typedef struct
{
int id;
char nojm[32];
int salar;
char phon[32];
} data_t;
int main(void) {
int i = 0;
data_t m[4];
while(fscanf(stdin,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
return 0;
}
I'm guessing the reason you're receiving a runtime error is that the character arrays you're using for strings (nojm and phon) are not long enough to process some of the entries in your text file, so memory is getting overwritten. Try increasing whatever length you're using to make sure it's greater than the longest string you'll encounter in your text file.
Another possibility is that you don't have enough items in your array to read in all the data from the text file. Here, I have a static array of 4 items to support the 4 from the text file. If your text file contains, say, 10,000 items you need to make sure you've properly allocated memory to store all of that.
You have
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
fscanf(fptr,"%d,%[^/,],%d,%s;", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon);
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
So you:
read with fscanf()
read with fscanf()
print what you read
As a result you print only what the second fscanf read. Delete the second one and you should be fine.
So, your code should be like this:
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
I see that you have problems compiling your code. I suspect that your code is relevant to my example, it might help.
#include <stdio.h>
#include <string.h>
/* Define the struct before main. */
struct person {
char phon[20];
int id;
};
// Give a synonym. Now struct person is the same with person_t.
typedef struct person person_t;
int main(void) {
person_t array[3]; // can hold 3 persons
FILE* fptr = NULL;
fptr = fopen("test.txt", "r");
int i = 0;
while (fscanf(fptr, "%d, %s", &array[i].id, array[i].phon) != EOF) {
printf("%d, %s\n", array[i].id, array[i].phon);
i++;
}
return 0;
}
and the test.txt
1, 697555555
2, 697888888
3, 694777777
I was wondering how to properly read a file and place each line in a string of arrays in C.
I have a file with the following written on it
one
two
three
four
I tried writing something like this:
int read_file(FILE *fp){
char readLine[MAX_LEN];
char *myarray[20];
int counter =0;
int i =0;
while(fgets(readLine,MAX_LEN,fp) != NULL){
myarray[counter] = readLine;
counter++;
}
/*printing the array*/
while(i<counter){
printf("%d %s",i,myarray[i]);
i++;
}
}
and the main would be something like
int main(){
FILE *fp;
fp = fopen("my.txt","r");
if(fp == NULL){
fprintf(stderr,"File does not exist");
return EXIT_FAILURE;
}
read_file(fp);
}
however, when printing I get:
four
four
four
four
even when I print using printf("%s",myarr[2]) , I still get four
Anyone knows what the problem may be?
You really need to make a copy of the line (by way of strdup()) as you are overwriting the buffer used to accept the input:
int read_file(FILE *fp){
char readLine[MAX_LEN];
char *myarray[20]; // Note char pointer!
int i, counter = 0;
while (counter < 20 && fgets(readLine,MAX_LEN,fp) != NULL) { // Note limit!
myarray[counter] = strdup(readLine);
counter++;
}
/*printing the array*/
for (i = 0; i < counter; i++)
printf("%d %s",i,myarray[i]);
/* free the lines */
for (i = 0; i < counter; i++)
free(myarray[i]);
}
myarray[counter] = readLine;
is the problem. You are overriding the read line pointer values each time.
use strcpy to copy the buffer content instead.
In addition as commented: you are not declaring array of strings, merely one string.
Change it to:
char myarray[4][20];
Of course, 4 is an example. Change it to any number of lines or use dynamic allocation.