Storing Strings from a File to an Array - c

I have read the strings from two files and stored them into two separate arrays, I then tried sorting them and writing them into another file...This part works the way it is supposed to but what I really need to do is combine the strings from the two arrays into one so that i can sort them in alphabetical order and then write to a file but the problem is that when i try to store these two arrays into one array I get segmentation fault as the error message..I am really not sure how to store these two arrays into another one so that I can sort it in order...I know how to sort it I am just not sure how to read these into an another array... i cant use #DEFINE because I am going to write all of this into a function for a tester code...
I have tried something like
new[i] = str;
and also:
strcpy(new[i],str)
but neither of these work...any help would be greatly appreciated...
Here is my code:
#include<stdio.h>
#include<string.h>
main (void)
{
char str[200];
char str2[300];
char new[300];
char temp [300];
int linenumber=0;
FILE *fa = fopen ("book1.dat", "r");
FILE *fb = fopen ("book2.dat", "r");
FILE *fc = fopen ("fixed.txt", "w");
int i=0;
int j=0;
int k;
/*read the strings into an array while it is not the end of file*/
while(!feof(fa)&& !feof(fb))
{
linenumber++;
fscanf(fa,"%[^\n]\n",str);
fscanf(fb,"%[^\n]\n",str2);
/*compare strings in array and write to array*/
if(strcmp(str2, str)<0)
{
fprintf(fc, "%s\n", str2);
fprintf(fc, "%s\n", str);
}
if (strcmp(str2,str)>0)
{
fprintf(fc, "%s\n", str);
fprintf(fc, "%s\n", str2)
}
/*print out the results of str */
printf("%s", str);
}
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* Type;
typedef struct vector {
size_t size;
size_t capacity;
Type *array;
} Vector;
Vector *vec_make(){
Vector *v;
v = (Vector*)malloc(sizeof(Vector));
v->size = 0;
v->capacity=16;
v->array=(Type*)realloc(NULL, sizeof(Vector)*(v->capacity *= 2));
return v;
}
void vec_add(Vector *v, Type value){
v->array[v->size] = value;
if(++v->size == v->capacity)
v->array=(Type*)realloc(v->array, sizeof(Vector)*(v->capacity *= 2));
}
size_t vec_size(Vector *v){
return v->size;
}
Type *vec_getArray(Vector *v){
return v->array;
}
void vec_free(Vector *v){
free(v->array);
free(v);
}
int cmp(const void *a, const void *b){
return strcmp(*(char**)a, *(char**)b);
}
void merge(const char *inpfile1, const char *inpfile2, const char *outfile){
FILE *fp;
char buff[256], **array;
Vector *v;
size_t c, size;
v = vec_make();
fp=fopen(inpfile1, "r");
while(NULL!=fgets (buff, 256, fp))
vec_add(v, strdup(buff));
fclose(fp);
fp=fopen(inpfile2, "r");
while(NULL!=fgets (buff, 256, fp))
vec_add(v, strdup(buff));
fclose(fp);
array=vec_getArray(v);
size=vec_size(v);
// qsort(array, size, sizeof(Type), cmp);
fp=fopen(outfile, "w");
for(c=0;c < size; ++c){
fputs(array[c], fp);
free(array[c]);
}
fclose(fp);
vec_free(v);
}
int main(){
merge("book1.txt", "book2.txt", "fixed.txt");
return 0;
}

Make new a char* array and use strdup to copy the string contained in str.

Related

Qsort array of strings in alphabetical order

Im trying to sort a array of strings I read from a file in alphabetical order using the qsort function. This is my code:
#include<stdio.h>
#include<stdlib.h>
#include<io.h>
#define MAXCHAR 256
int main(int argc, char **argv){
char tempList[MAXCHAR][MAXCHAR];
char reader[MAXCHAR];
FILE* fp;
int i;
char *n;
int index = 0;
if(argc != 2){
printf("too few arguments\n");
exit(-1);
}
fp=fopen(argv[1], "r");
if(fp == NULL){
printf("failed to open file\n");
exit(-1);
}
while(!feof(fp)){
fgets(reader, MAXCHAR, fp);
n = strchr(reader, '\n');
if(n != NULL){
*n = '\0';
}
strcpy(tempList[index], reader);
index++;
}
index--;
for(i=0; i<index; i++){
printf("%s\n", tempList[i]);
}
qsort(tempList, index, sizeof(char *), strcmp);
for(i=0; i<index; i++){
printf("%s\n", tempList[i]);
}
}
When I run the program, the list doesn't get sorted at all. I also tried methods posted on this website that asks a similar question and they all give me segmentation faults. Is there something wrong with the code?
Here is part of the content of the txt file. It is a list of 40 names:
Liam
Alexander
Mia
Noah
Emma
William
Charlotte
Charlotte
Mason
William
Ethan
Ethan
Liam
Alexander
Liam
Sophia
Emily
Mason
Alexander
You have a bona fide array of arrays; not an array of char*. Arrays aren't pointers. qsort expects the stride of the elements in the sequence being sorted. As your sequence is declared as:
char tempList[MAXCHAR][MAXCHAR];
the proper element size is the size of the inferior element size. In this case you have an array of size MAXCHAR of array of char of size MAXCHAR (an array of arrays).
Thus this is wrong:
qsort(tempList, index, sizeof(char *), strcmp);
// wrong size ==============^^^^
the size of each element should be:
qsort(tempList, index, sizeof tempList[0], strcmp);
// correct size ==============^^^^
The other issues in your program will eventually grief you and are covered in general comments below your question, but this is the fundamental problem preventing your sorting from working correctly. A retooled version of your program appears below, addressing most of those concerns:
Updated Source
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCHAR 256
/* properly declared for compatibility with qsort */
static int cmp_str(const void *lhs, const void *rhs)
{
return strcmp(lhs, rhs);
}
/* main entrypoint */
int main(int argc, char **argv)
{
char tempList[MAXCHAR][MAXCHAR];
FILE* fp;
size_t i, index = 0;
if(argc != 2)
{
printf("too few arguments\n");
return EXIT_FAILURE;
}
fp=fopen(argv[1], "r");
if(fp == NULL)
{
perror(argv[1]);
return EXIT_FAILURE;
}
while(index < MAXCHAR && fgets(tempList[index], sizeof(*tempList), fp) != NULL)
{
char *n = strchr(tempList[index], '\n');
if(n != NULL)
*n = 0;
if (*(tempList[index])) /* don't insert blank lines */
++index;
}
for(i=0; i<index; i++)
printf("%s\n", tempList[i]);
fputc('\n', stdout);
qsort(tempList, index, sizeof tempList[0], cmp_str);
for(i=0; i<index; i++)
printf("%s\n", tempList[i]);
return EXIT_SUCCESS;
}
Untested, but it should be pretty close.
Best of luck.
Your size value in qsort(tempList, index, sizeof(char *), strcmp); is wrong.
It should be qsort(tempList, index, sizeof(*tempList), strcmp);.
I have tried to fix your code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//#include<io.h> it's not standart
#define MAXCHAR 256
// I implement the function because the warning is that
// Incompatible pointer types passing 'int
// (const char *, const char *)' to parameter of type
// 'int (*)(const void *, const void *)'
// Already qsort() prototype is
// void qsort(void* ptr, size_t count, size_t size,
// int (*comp)(const void*, const void*));
// I think that the warning can be ignored strcmp also can be used
int myCompare(const void* a, const void* b)
{
const char* aa = (const char*)a;
const char* bb = (const char*)b;
return strcmp(aa, bb);
}
int main(int argc, char **argv){
char tempList[MAXCHAR][MAXCHAR];
char reader[MAXCHAR];
FILE* fp;
int i;
char *n;
int index = 0;
if(argc != 2){
printf("too few arguments\n");
exit(-1);
}
fp=fopen(argv[1], "r");
if(fp == NULL){
printf("failed to open file\n");
exit(-1);
}
while(fgets(reader, MAXCHAR, fp) != NULL){ // !feof is not recommended search why
n = strchr(reader, '\n');
if(n != NULL){
*n = '\0';
}
strcpy(tempList[index], reader);
index++;
}
/*
printf("%lu\n",sizeof(reader)); //256
printf("%lu\n",sizeof(*reader)); //1
printf("%lu\n",sizeof(*tempList)); //256
printf("%lu\n",sizeof(**tempList)); //1
*/
for(i=0; i<index; i++){
printf("%s\n", tempList[i]);
}
qsort(tempList, index, sizeof(*tempList), myCompare);
printf("\n\nAfter sorting\n\n");
for(i=0; i<index; i++){
printf("%s\n", tempList[i]);
}
}

C Program double free or corruption error

Currently working on a concordance program in C. When I try to run the program though, I get an error.
This is my C program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void print(char Table, int n) {
printf("%d: ", n+1); // Prints the table
}
int insert(const void *bb, const void *cc) {
return strcmp(*(const char **)bb, *(const char **)cc);
}
void empty(char *Table[]) {
strcat(Table,"NULL"); // Empties the table
}
int main(int argc, char *argv[]){
if(argc!=3){
printf("ERROR: Usage: concordance table_size"); // Errors due to not enough variables (Should be tablesize and file name)
} else {
FILE *fp; //This block opens the file user has inputted and makes the string "File_contents" set to the file's contecnts
fp = fopen(argv[2],"r");
char *file_contents;
long input_file_size;
fseek(fp, 0, SEEK_END);
input_file_size = ftell(fp);
rewind(fp);
file_contents = malloc((input_file_size + 1) * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, fp);
fclose(fp);
file_contents[input_file_size] = 0;
char *word, *words[strlen(file_contents)/2+1];
int i, n;
for(i=0;file_contents[i];i++){
file_contents[i]=tolower(file_contents[i]); //Converts all words to lower case
}
i=0;
word = strtok(file_contents, " ,.-:;?!"); //Chars which signal end of word
while(word != NULL) {
words[i++] = word;
word = strtok(NULL, " ,.-:;?!");
}
n = i;
qsort(words, n, sizeof(*words), insert);
for(i=0; i<n; ++i){
print(words[i],i);
printf("%s\n", words[i]);
}
empty(words);
fclose(fp); // Closes open file
}
return 0;
}
And the following is the error I'm getting:
* glibc detected * concordance: double free or corruption (!prev): 0x0000000001060f010
Not sure what could be causing this error to happen. Any help on this would be great though.
You aren't calling fclose() twice. Which I suppose in turn might call free() internally. Remove the fclose() at the end of the program.
you are passing NULL as argument to strtok function. I think this may cause the problem

Open a file in C - Why isn't it loading all the matrix or deleting \n?

I'm tring to build a simple program where i say the dimensions of a matrix i want, and i read that size from a txt file to a 2D array.
So i have the following letters as it is, in a txt file called soup.txt
ORCA
RAIO
ATNS
I want this 3x4 matrix to be loaded to an array. This are the structs and the functions that i have:
typedef struct dicionario{
char matrix[200][200];
}*DICIONARIO;
//Function to load the matrix
void abresopa(FILE *fs, char *s,DICIONARIO sopa,int dimy,int dimx){
int i;
fs=fopen (s,"r");
for (i=0;i<dimy;i++)
fgets(sopa->matrix[i],dimx,fs);
limpabn(sopa->matrix[i]);
}
//Clears \n at the end of a string
void limpabn (char *s){
int i;
for (i=0;s[i]!='\n';i++); if (s[i]=='\n') s[i]='\0';
}
My main looks like this. I'm opening the file and printing the matrix:
int main(){
struct dicionario sopa;
DICIONARIO y=&sopa;
int dimy=3, dimx=4;
FILE *fs;
abresopa(fs,"soup.txt",y,dimy,dimx);
for (i=0;i<dimy;i++) printf("%s",y->matrix[i]);
return 0;}
I was hoping to print this:
ORCARAIOATNS
But i got this instead
ORCA
RAI
What am i doing wrong?
Regards
for (i=0;i<dimy;i++)
fgets(sopa->matrix[i],dimx,fs);//<-- dimx is small size for read (XXXX\n\0)
limpabn(sopa->matrix[i]);//<- outside for-loop
shoud be
for (i=0;i<dimy;i++){
fgets(sopa->matrix[i],dimx+2,fs);
limpabn(sopa->matrix[i]);
}
fgets is used like this:
char line[256];
fgets(line, sizeof line, fp);
char *p = strchr(line, '\n');
if (p) *p = '\0';
This is a working instance. Note that array widths are just as an example. It's not very difficult to load the result a matrix.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void strip(char *s)
{
char *p2 = s;
while (*s != '\0')
{
if (*s != '\n')
{
*p2++ = *s++;
}
else
{
++s;
}
}
*p2 = '\0';
}
int main()
{
char mx[1024];
char line[200];
FILE *f = fopen("file.txt", "r");
int i = 0;
while (fgets(line, 200, f))
{
strip(line);
if (i == 0)
{
strcpy(mx, line);
}
else
{
strcat(mx, line);
}
i++;
}
printf("%s\n", mx);
return 0;
}

Reading from a file into an array of chars

I'm trying to read a list of strings from a file to an array.
in file it looks like this
ItemOne
ItemTwo
ItemThree etc.
I declared an array as:
char** array;
and file as:
FILE *read;
This is what I came up with:
{
i = 0;
printf("Type in the name of the file\n");
scanf("%s", &name);
read = fopen(name, "r");
if (read == NULL)
{
perror("Doesn't work");
return 1;
}
else
{
array = malloc(100 * sizeof(*array));
while (!feof(read))
{
array[i] = malloc(32 * sizeof(*array[i]));
fscanf(read, "%s", &array[i]);
i++;
}
}
}
Tt compiles, but when I try to display the array it's empty. Any ideas?
while (!feof(read))
{
array[i] = malloc(32 * sizeof(*array[i]));
fscanf(read, "%s", array[i]); //You should pass a pointer to a pointer to array of chars
i++;
}
I hope it'll work...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long GetFileSize(FILE *fp){
long fsize = 0;
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
fseek(fp,0,SEEK_SET);//reset stream position!!
return fsize;
}
char *ReadToEnd(const char *filepath){
FILE *fp;
long fsize;
char *buff;
if(NULL==(fp=fopen(filepath, "rb"))){
perror("file cannot open at ReadToEnd\n");
return NULL;
}
fsize=GetFileSize(fp);
buff=(char*)malloc(sizeof(char)*fsize+1);
fread(buff, sizeof(char), fsize, fp);
fclose(fp);
buff[fsize]='\0';
return buff;
}
char** split(const char *str, const char *delimiter, size_t *len){
char *text, *p, *first, **array;
int c;
char** ret;
*len = 0;
text=strdup(str);
if(text==NULL) return NULL;
for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item
if(c==0) first=p; //first token top
ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL
if(ret==NULL){
free(text);
return NULL;
}
strcpy(text, str+(first-text));//skip until top token
array=ret;
for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){
*array++=strdup(p);
}
*array=NULL;
*len=c;
free(text);
return ret;
}
void free4split(char** sa){
char **array=sa;
if(sa!=NULL){
while(*sa)
free(*sa++);//for string
free(array); //for array
}
}
int main(){
char *text, **lines;
size_t line_count;
text=ReadToEnd("data.txt");
lines=split(text, "\r\n", &line_count);
free(text);
{ //test print
int i;
for(i=0;i<line_count;++i)
printf("%s\n", lines[i]);
}
free4split(lines);
return 0;
}

merging and sorting a text file in C

I am supoosed write a function that reads two text files line by line, compare them, delete the duplicates and but them into a third file in alphabetical order...I have been working on this for over a month and I am still stuck I have tried several ways to do this and come up with nothing...I was in formed that i have to use strcmp to do this and I cant use any other predefined sorting function...I have also looked around on this site and cannot find much that helps with this...any help would be greatly appreciated..Here is what I have so far:
#include<stdio.h>
#include<string.h>
main (void)
{
char str [200];
char str2 [200];
char new [100];
char temp [100];
int row = 10;
FILE *fa = fopen ("book1.dat", "r");
FILE *fb = fopen ("book2.dat", "r");
FILE *fc = fopen ("fixed.txt", "w");
int i;
int j;
int k;
while (fgets (str, 200, fa) !=NULL && fgets (str2, 200, fb) !=NULL)
{
puts(str);
puts(str2);
if (strcmp( str, str2) ==0 )
{
strcpy (str , new);
} else {
strcpy (new, str);
strcpy (new, str2);
}
}
for ( i = 0; i < row; i++)
{
for (j = i+1; j< row; j++)
{
if(strcmp(new[i], new [j]) > 0)
{
strcpy (temp, new);
strcpy(new, new);
strcpy(new, temp);
}
}
}
for (i = 0; i < length; i ++)
{
fputs(new, fc);
}
}
Your use of strcpy() is peculiar. Recall its signature:
char *strcpy(char *dest, const char *src)
Here's a usage that doesn't make immediate sense to me:
strcpy (new, str); // new now has str
strcpy (new, str2); // new now has str2
You've effectively overwritten something there. I would start from there, and see what else may not be working as you intend. Furthermore, if you can use gcc, look into using gdb as well to debug your code. (You would need to compile with the -g flag.)
First off, can you assume the duplicates from book1 and book2 line up nicely?
Think about how you would detect if the first entry in book1 is identical to the last entry in book2.
Secondly, you have to sort your output alphabetically. Sorting algorithms is kind of one of those common things that students are forced to do all the time. It builds character. For bonus kudos, implement quick sort.
sample a way.
error handling is omitted.
since we are using the sort function of the library sqort, implement your own.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_MAX_SIZE 256
typedef struct filePos {
FILE *fp;
long pos;
} FilePos;
typedef struct myfile {
int lines;
int capacity;
FILE *fp;
FilePos *filePoss;
} MyFile;
MyFile *myfopen(const char *filepath){
char buff[LINE_MAX_SIZE];
MyFile *mfp;
mfp = (MyFile*)malloc(sizeof(MyFile));
mfp->lines = 0;
mfp->capacity=16;
mfp->filePoss=NULL;
mfp->filePoss=(FilePos*)realloc(mfp->filePoss, sizeof(FilePos)*(mfp->capacity *= 2));
mfp->fp = fopen(filepath, "r");
do{
mfp->filePoss[mfp->lines].fp = mfp->fp;
mfp->filePoss[mfp->lines].pos = ftell(mfp->fp);
if(++mfp->lines == mfp->capacity){
mfp->filePoss=(FilePos*)realloc(mfp->filePoss, sizeof(FilePos)*(mfp->capacity *= 2));
}
}while(NULL!=fgets(buff, LINE_MAX_SIZE, mfp->fp));
--mfp->lines;
return mfp;
}
void myfclose(MyFile *mfp){
free(mfp->filePoss);
fclose(mfp->fp);
free(mfp);
}
char *myfgets(FilePos *p, char *buff){
fseek(p->fp, p->pos, SEEK_SET);
return fgets(buff, LINE_MAX_SIZE, p->fp);
}
int myfcomp(const void *a, const void *b){
char buff_a[LINE_MAX_SIZE];
char buff_b[LINE_MAX_SIZE];
FilePos *fpa,*fpb;
fpa=(FilePos*)a;
fpb=(FilePos*)b;
myfgets(fpa, buff_a);
myfgets(fpb, buff_b);
return strcmp(buff_a, buff_b);
}
void myfsort(MyFile *mfp){
qsort(mfp->filePoss, mfp->lines, sizeof(FilePos), myfcomp);
}
void myfprint(MyFile *mfp){
char buff[LINE_MAX_SIZE];
int i;
for(i=0;i<mfp->lines ;++i)
printf("%s", myfgets(mfp->filePoss + i, buff));
}
void merge(const char *inpfile1, const char *inpfile2, const char *outfile){
FILE *fo;
MyFile *fi1, *fi2;
char buff_f1[LINE_MAX_SIZE];
char buff_f2[LINE_MAX_SIZE];
char buff_fo[LINE_MAX_SIZE];
char *outbuff=NULL;
int fi1_line, fi2_line;
int eof1, eof2;
fo=fopen(outfile, "w");
fi1=myfopen(inpfile1);
fi2=myfopen(inpfile2);
myfsort(fi1);
myfsort(fi2);
fi1_line=fi2_line=0;
eof1=eof2=0;
*buff_fo='\0';
while(1){
if(!eof1 && outbuff != buff_f2){
myfgets(&(fi1->filePoss[fi1_line]), buff_f1);
}
if(!eof2 && outbuff != buff_f1){
myfgets(&(fi2->filePoss[fi2_line]), buff_f2);
}
if(!eof1 && !eof2){
if(strcmp(buff_f1, buff_f2) <= 0){
outbuff=buff_f1;
++fi1_line;
} else {
outbuff=buff_f2;
++fi2_line;
}
} else if(!eof1 && eof2){
outbuff=buff_f1;
++fi1_line;
} else if(eof1 && !eof2){
outbuff=buff_f2;
++fi2_line;
} else {
break;
}
if(strcmp(outbuff, buff_fo) != 0){//duplicate check
strcpy(buff_fo, outbuff);
fputs(buff_fo, fo);
}
if(fi1->lines == fi1_line)
eof1 = !0;
if(fi2->lines == fi2_line)
eof2 = !0;
}
myfclose(fi2);
myfclose(fi1);
fclose(fo);
}
int main(){
merge("book1.txt", "book2.txt", "fixed.txt");
return 0;
}

Resources