I have a problem, my program in C have to find words with N letters, count them and sort them in lexicographical order and save them to an another file. I've done the first 2 things, but sorting them and save to the file doesn't work. It saves only the last word to the second file... do you have any idea why?
this is my code:
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <stddef.h>
#include <string.h>
int main()
{
FILE *r, *fp;
char ch[100];
int n,i,j,x=0;
r=fopen("text.txt","r");
fgets(ch, 100, r);
char *s = ch;
char *p = s;
printf("Give the length of word: ");
scanf("%d",&n);
printf("\n\nWords with %d letters: \n\n",n);
while (*p) {
char *start;
int len;
while (*p && isspace(*p))
++p;
start = p;
while (*p && !isspace(*p))
++p;
len = p - start;
fp=fopen("text2.txt","w");
if (len == n) {
printf("%.*s\n", len, start);
x++;
fprintf(fp,"%.*s",len, start);
}
}
printf("\nNumber of words: %d ",x);
fclose(fp);
getch();
fclose(r);
}
my input file:
hi my name is Zsolt this program if for displaying words with N letters count them and sort them alphabeticaly a save them to an another file
It is because you open text2.txt in every iteration of your while loop. And what is more, you open it with mode "w" which if you look at the documentation states:
write: Create an empty file for output operations. If a file with the same name already exists, its contents are discarded and the file is treated as a new empty file.
So what is happening is, at every iteration, you open the file, discarding whatever was there before, (which after the first iteration would be a file with a single word in it).
Instead you should open it before you enter the while loop.
Additionally, you stated that you wanted to sort the words you found in lexicographical order before you wrote them to the new file. If your code had written the words as you had intended, then they would be in the order they appeared in the original file, not lexicographic order. You are better off saving the pointers to the n-length words in an array, sorting that array, and then writing it all in one go to your output file.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_WORDS 100
int
qstrcmp(const void *a, const void *b)
{
const char
*s = *(const char **)a,
*t = *(const char **)b;
return strcmp(s, t);
}
int
main()
{
FILE *input, *output;
input = fopen("text.txt", "r");
// Get length to filter by
unsigned long n;
scanf("%lu", &n);
char *words[MAX_WORDS];
int i = 0;
// Find words of correct length
char buf[100];
while (fscanf(input, "%99s", buf) != EOF) {
// Protect from buffer overflow
if (i >= MAX_WORDS) {
printf("Too many words!");
break;
}
if (strlen(buf) == n) {
words[i++] = strncpy(malloc(n+1), buf, n+1);
}
}
fclose(input);
// Sort in lexicographical order.
qsort(words, i, sizeof(char *), qstrcmp);
// Write to output
output = fopen("text2.txt", "w");
for (int j = 0; j < i; ++j) {
fprintf(output, "%s\n", words[j]);
}
fclose(output);
// Print number found.
printf("Found %d word%s of length %lu.\n", i, i == 1 ? "": "s", n);
return 0;
}
Implementation Notes
Sorting is achieved with qsort from "stdlib.h".
Pay attention to buffer overflows! In this case I just bail, but alternatively, you could re-allocate the memory for the words array.
Remember to copy the null-byte over when saving the word.
qsort passes references to the array elements it's sorting to its comparator function, so it will pass values of type const char **, this is why we need to use the qstrcmp wrapper function.
Related
I'm working on a project using C and for the project I must read in a text file and store each word into an array. I also have to remove the punctuation off the words, so I need to use a 2-Dimensional array in order to edit the words. I am having trouble figuring out how to get the words in the 2-D array it self. This is what I have done so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1001
#define LINES 81
int main(void) {
int stringSize;
int i =0;
char *x[MAX][LINES];
char str[MAX];
char y[MAX];
FILE *fp;
fp = fopen("TwoCitiesStory.txt","r");
if(fp == NULL) {
printf("Cannot open file.\n");
exit(1);
}
while(!feof(fp)) {
for(i=0;i<MAX;i++){
fscanf(fp,"%s",x[i][LINES]);
}
}
return 0;
}
The following line
char *x[MAX][LINES];
declared a 2D array of pointers. What you need is just a 2D array of characters.
char x[MAX][LINES];
The code for reading the words can be simplified to:
while( i < MAX && fscanf(fp, "%80s", x[i]) == 1 )
{
++i;
}
Read the whole line using fgets()
Store the read line into the 2D array
The whole code looks like
char x[row][col];
char buf[300];
int i=0,j=0;
memset(x,0,sizeof(x));
while(fgets(buf,sizeof(buf),fp))
{
size_t n = strlen(buf);
if(n>0 && buf[n-1] == '\n')
buf[n-1] = '\0';
if(i>= row && n> col)
break;
strcpy(x[i],buf);
i++;
}
Edits:
If you need each word separately in the array.
buf is being used to read the whole line.
strtok() is used to break the line into words with space as delimiter.
Then store each word in each row.
size_t n;
while(fgets(buf,sizeof(buf),fp))
{
char *p = strtok(buf," ");
while( p != NULL)
{
n = strlen(p);
if(i>= row && n> col)
break;
strcpy(x[i],p);
i++;
p = strtok(NULL," ");
}
}
If you want to print out the array go for
int i;
for(i=0;i<row;i++)
printf("%s\n",x[i]);
Why feof() is wrong
Alright, I am seriously puzzled.
I used a snippet of code that would open and read a file and store it in dynamic memory. The output is executed in a void function, where the file is given line by line. The size of the buffer character array was specified because the number of bytes that each line contains is unknown. I want to compare the string that is read with a user input (given by char *word) to see if the program works or not.
In my mind, the strings can only be the same if both their sizes and their character sequences are equivalent, and the dynamic string size is not the same as the file's string size. By using the counter in the main () loop (i.e. pos), I can determine the correct size of the string being read from the file and pass it on to the void function. In the void handle_line function I copied in the characters from the buffer into char *temp because I know the number of characters that temp needs (i.e. pos) and can therefore initialize its size and copy the contents of the dynamic memory into the char *temp. I proceeded to print out the bytes of the string sizes for line, temp, and word. While char *temp and char *word gave their expected values, char *line was always four bytes. Furthermore, the strcmp() did not give the expected result when H2O was read from the CompoundLib file--this in spite of the fact that I know that their sizes and character sequences are the same.
How can this be? What am I missing??? Many thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void handle_line(char *line, int a) {
char temp[a];
int i=0;
char temp_2[a];
char *word="H2O";
for(i=0;i<=a;i++)
temp[i]=line[i];
temp_2[i]=temp[i];
printf("size of temp= %d\n",sizeof temp_2);
printf("size of word= %d\n",sizeof word);
printf("size of line= %d\n",sizeof line);
if (strcmp(temp_2, word) == 0)
puts("Strings equal");
else
puts("Strings do not equal");
printf("%s\n", line);
printf("%d\n", a);
printf("%s\n",temp);
}
int main(int argc, char *argv[]){
char c[1000];
FILE *fptr;
int size = 1024, pos;
int c;
char *buffer = (char *)malloc(size);
FILE *f = fopen("CompoundLib.txt", "r");
if(f) {
do { // read all lines in file
pos = 0;
do{ // read one line
c = fgetc(f);
if(c != EOF) buffer[pos++] = (char)c;
if(pos >= size - 1) { // increase buffer length - leave room for 0
size *=2; //size = size*2
}
}while(c != EOF && c != '\n');
buffer[pos] = 0;
handle_line(buffer, pos);
} while(c != EOF);
fclose(f);
}
free(buffer);
return 0;
}
I'm new to programming,and I have a small problem.
I have a file named questions.txt containing a string of questions, I want to read the string from the file then split it into array with each question having an index, for example a[i] = "Question i" etc.
I did so many tries, but it always ends up reading the last line in the file, when write a loop the program stops working.
This is what i came up with, it's all probably wrong:
char str[200];
char *ptr;
FILE * fp = fopen("questions.txt", "r");
while(fgets(str, 200, fp)!= NULL)
printf("%s", str);
ptr = strtok(str, "\n");
while(ptr != NULL)
{
ptr = strtok(str, "\n");
printf("%s\n", ptr);
ptr = strtok(NULL, "\n");
}
fclose(fp);
The file is:
what is your course?
who is your instructor?
Output i get is:
what is your course?
who is your instructor?
who is your instructor?
I want to read the string from the file then split it into an array with each question having an index...
Let me say, that you don't have a string to split into array.
You should better have a file with a one string of questions like this:
what is your course?:who is your instructor? // `:` is some kind of delimiter
I can suppose that you want to make a vector (one dimensional array) of the file. And in that vector, each element will contain a question from the file. Right?
I can share with you a function from my library I've made at the university. I'll write here a simple program. But it uses delimiters - :, for example. You can modify this function for working without delimiters -- this only depends on you.
In two words, this little program does the following:
// BEFORE: you have a string that ends with a null terminating character.
Question_1_abcbadsad:QUestion_2asasdasd:Question_3sldasdsa\n
^
here ^<< printing 'string' stops
// AFTER: an array of questions. Each of them ends with a null terminating character.
Question_1_abcbadsad\nQUestion_2asasdasd\nQuestion_3sldasdsa\n
^
^<< printing argz[0] will stop here
main.c
#include "argz.h"
int main()
{
error_t func;
char *argz; // pointer to a vector; to an array of questions
size_t argz_len;
// size of that vector (the size of the string you've got from the file)
// Consider `string` to be your `ptr`. You read a string from the file so
// `ptr` will point to the string.
char *string = "Question_1_abcbadsad:QUestion_2asasdasd:Question_3sldasdsa";
// Here `:` is a separate character.
func = argz_create_sep(string, ':', &argz, &argz_len);
if(func == OK)
argz_print(argz, argz_len);
else
printf("ERROR\n");
return 0;
}
argz.c
#include "argz.h"
error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len)
{
int i;
char *ch;
int len = strlen(string);
if(len==0)
return ENOMEM;
*argz = (char*) malloc (sizeof(char)*(len + 1));
strcpy(*argz, string);
*argz_len = strlen(*argz);
ch = *argz;
for(i = 0; i < len; i++) {
if(*ch == sep) *ch='\0';
ch++;
}
return OK;
}
void argz_print(const char *argz, size_t argz_len)
{
const char *ch;
int i;
ch = argz;
for(i = 0; i < argz_len; i++) {
if(*ch == '\0')
printf("\n");
else
printf("%c",*ch);
ch++;
}
printf("\n\n\n");
}
argz.h
#include <stddef.h> // for size_t
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef enum {OK, ENOMEM} error_t;
/* function prototypes */
error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len);
void argz_print (const char *argz, size_t argz_len);
I think what you want is something like this:
#include <stdio.h>
int main(){
int i=0;
char str[200],s='1'; //s is give a random character
FILE * fp = fopen("questions.txt", "r");
while (s!=EOF){ //works until s= the end of file
s=getc(fp); //s starts to receive characters from text file
str[i]=s; //each character of text is placed into the string array
i++;
}
str[i]='\0'; //s reached EOF so lets indicate where we stopped in the string
fclose(fp);
printf("%s\n",str);
//EDIT: changing 1D str to 2D str2
char str2[10][200]; // 10 for max no. of questions, 200 - length of each question
int j=0,k=0;
i=0;
for(j=0;j<200;j++){
str2[i][k]=str[j];
k++;
if (str[j]=='\n'){
i++;
k=0;}
}
for(i=0;i<10;i++) //prints your 2D string array
printf("%s",str2[i]); //after the last question there will be junk
return 0;
}
how can I access an array outside a loop which was populated inside a while loop ?
Main.c
#define _CRT_SECURE_NO_WARNINGS
#include "Definition.h"
#include <stdio.h>
#include <string.h>
#include <pthread.h>
extern int Readline(),CountWord();
char Line[500]; /* one line from the file */
char myFileList[300][MaxLine];
char myFileList2[300][MaxLine];
char myFileList3[300][MaxLine];
char myFileList4[300][MaxLine];
int NChars = 0, /* number of characters seen so far */
NWords = 0, /* number of words seen so far */
NLines = 0, /* number of lines seen so far */
LineLength; /* length of the current line */
void *ThreadTask(void *threadarg)
{
//receive array
//match each element with file name in directory
//perform counts on each file
//print store or return values
//printf("%s",myFilesList);
}
FILE *filep;
int main(int argc, char **argv)
{
int i = 0;
filep = fopen(argv[1], "r");
if (!filep){
printf("No %s such file found\n", argv[1]);
return -1;
}
while ((LineLength = Readline(filep))!=0) //here in this loop I split a big file into 4 arrays depending on the number of lines(240). How can I access these newly created arrays outside the while loops. I need to pass them to individual threads as arguments.
{
if(i>=0 && i<60){
strcpy(myFileList[i], Line);
printf("%s\n", myFileList[i]);
i++;
}
if(i>=60 && i<120){
strcpy(myFileList2[i], Line);
//printf("%s\n", myFileList2[i]);
i++;}
if(i>=120 && i<180){
strcpy(myFileList3[i], Line);
//printf("%s\n", myFileList3[i]);
i++;}
if(i>=180){
strcpy(myFileList4[i], Line);
//printf("%s\n", myFileList4[i]);
i++;}
}
fclose(filep);
}
Readline.c
#include "Definition.h"
#include "ExternalVar.h"
#include <stdio.h>
int Readline(FILE *filep)
{
//Please implement your code here
int i = 0;
char ch;
while (!feof(filep) && i<MaxLine){
ch = fgetc(filep);
if (ch == '\n'){
break;
}
Line[i] = ch;
i++;
}
Line[i] = 0;
return i;
}
whats the easiest way to pass the four arrays created in the while loop to threads as arguments? I every time I try to print out the arrays outside of the while loop there is nothing and when I try to print them out inside the while loop but outside the if loops then they only display the 1st line 60 times.
If using PThreads use the last parameter of pthread_create() to pass an argument to the tread-function.
You must pass the pointer to the array to ReadLine... It's good practice to pass the maximum length, too, to avoid buffer overflows errors.
#define MAXLEN 240
char Line[MAXLEN+1];
while ((LineLength = Readline(filep, Line, MAXLEN))!=0)
{
...
}
int Readline(FILE *filep, char *Line, int maxlen)
{
...
I'm trying to reverse a string from a text file using recursion into another text file. The reversed string will be stored in a char array, and buffer will become that array. buffer will then be fprintf-ed to the new file. This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
reverse(char *ch, char *str) //receives "buffer" as argument. str traverses ch
{
char array[20]; //will store the reversed string
if(*str == '\0')
return 0; //arrived at end of string
return(reverse(ch, str+1) + 1); //don't know if this is correct
}
//I want to use the returned number as the index number. For example, if I have
//string "abcd", string[0]='d', string[1]='c', string[2]='b', string[3]='a'. Problem is,
//how do I do it?
int main(int argc, char *argv[]) //argv[1] is input file. argv[2] is output file printed backwards
{
FILE *fp1, *fp2;
char *p, buffer[20]; //p points to buffer
fp1 = fopen("a.txt", "r");
if(fp1 == NULL)
{
printf("The file does not exist.\n");
return 0;
}
p = buffer;
while(fgets(buffer, 20, fp1) != NULL) //reads the first 20 characters of file.txt into buffer
{
reverse(buffer, p); //passes "buffer" as argument
fprintf(fp2, "%s\n", buffer);
}
printf("File %s has been successfully reversed into file %s!\n", argv[1], argv[2]);
fclose(fp1);
fclose(fp2);
return 0;
}
Since I am new to recursion, I only have the faintest idea of how to implement my reverse function.
Reversing a string is easier and faster via an iterative loop, but to make a recursive function you could have the function reverse the starting and ending chars, then repeat the process with the smaller string
abcde
^ ^ first call
^ ^ next call
^ end
---
void reverse(char *s, char *e) {
char tmp = *s;
*s++ = *e;
*e-- = tmp;
if (e > s) reverse (s, e);
}
Where s points to the 1st char and e to the last char. Note that the initial string must have a length > 0 (or a test could be added to the function).
Exemple
int main () {
char x[] = "abcde";
reverse(x, x+strlen(x)-1);
printf("%s\n", x);
return 0;
}
outputs edcba.