C Turning lines of an archive into arrays - c

I have an archive and I want to turn every line into an array: v[i].data.
However, when I run the code it shows zeros for the arrays.
Is there anything I should change?
Input
1760
02/20/18,11403.7
02/19/18,11225.3
02/18/18,10551.8
02/17/18,11112.7
02/16/18,10233.9
Actual Output
1761
0
Expected Output
1761
02/20/18,11403.7
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct{
char data[20];
}vetor;
int main(int argc,char *argv[]){
FILE *csv;
if((csv=fopen(argv[1], "r")) == NULL )
{
printf("not found csv\n");
exit(1);
}
long int a=0;
char linha[256];
char *token = NULL;
if(fgets(linha, sizeof(linha), csv)) //counting lines
{
token = strtok(linha, "\n");
a =(1 + atoi(token));
}
printf("%d\n", a);
rewind(csv);
vetor *v;
v=(vetor*)malloc(a*sizeof(vetor));
char linha2[256];
while (fgets(linha2, sizeof(linha2), csv) != 0)
{
fseek(csv, +1, SEEK_CUR);
for(int i=0;i<a;i++)
{
fscanf(csv, "%[^\n]", v[i].data);
}
}
printf("%s\n", v[0].data);
fclose(csv);
return 0;
}

There were a number of mistakes so I went ahead and rewrote the problem areas with comments explaining what I did
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char data[20];
}vetor;
int main(int argc,char *argv[]){
FILE *csv;
if((csv=fopen(argv[1], "r")) == NULL )
{
printf("not found csv\n");
exit(1);
}
char line[20];
// Read number of lines
int num_lines = 0;
if (!fgets(line, sizeof(line), csv)) {
printf("Cannot read line\n");
exit(1);
}
char* token = strtok(line, "\n");
num_lines = atoi(token) + 1;
vetor* v = malloc(num_lines * sizeof(vetor));
// Fill in vetor
int i = 0;
while (fgets(line, sizeof(line), csv) != NULL) {
int len = strlen(line);
line[len-1] = '\0'; // replace newline with string terminator
strcpy(v[i].data, line); //copy line into v[i].data
i++;
}
printf("%d\n", num_lines);
for (i = 0; i < num_lines; i++) {
printf("%s\n", v[i].data);
}
return 0;
}
I think the main mistake was a misunderstanding of how best to read in each line of information. If I understood correctly you want each 02/20/18,11403.7 line to be an element in the vetor array.
The easiest way is to simply get each line one at a time with fgets
while (fgets(line, sizeof(line), csv) != NULL)
Change the ending character from newline to the string terminating character '\0'
int len = strlen(line);
line[len-1] = '\0';
Then copy the string into the ith element of vetor and update i for the next iteration of the loop.
strcpy(v[i].data, line);
i++;

Related

How would I create an array of char* after reading an unknown number of strings (each of unknown length) from a file? [duplicate]

This question already has answers here:
How should character arrays be used as strings?
(4 answers)
Closed 12 months ago.
I have a file with an unknown number of strings and each of these strings is of an unknown length.
I would like to make each line of the file its own string in an array of strings.
I tried to use dynamic allocation in a char** array, but I don't think I'm approaching this correctly.
Below is the code I have tried. It's getting stuck in an infinite loop, and I can't figure out why.
(The text file I'm reading from ends with a line break, by the way.)
#include <getopt.h> //for getopts
#include <sys/stat.h> //to do file stat
#include <dirent.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h> //user macros
#include <stdlib.h>
#include <stdbool.h>
#include <libgen.h>
#include <errno.h>
int main(int argc, char *argv[]) {
//storing the filename inside string
char* filename = argv[1];
FILE *fp1 = fopen(filename, "r");
if (fp1 == NULL) {
fprintf(stderr, "Error: Cannot open '%s'. No such file or directory.\n", filename);
return EXIT_FAILURE;
}
/**
* we begin by getting the number of numbers in the file
* the number of numbers = number of lines = number of line breaks
*/
size_t numNumbers = 0;
// while((fscanf(fp1, "%*[^\n]"), fscanf(fp1, "%*c")) != EOF){
// numNumbers = numNumbers + 1;
// }
char c;
while((c = fgetc(fp1)) != EOF){
if(c == '\n'){
numNumbers++;
}
}
fclose(fp1);
FILE *fp2 = fopen(filename, "r");
char** arrayOfStrings = malloc(numNumbers * sizeof(char*));
for(int i = 0; i < numNumbers; i++) {
int len = 0;
if(((c = fgetc(fp1)) != '\n') && (c != EOF)){
len++;
}
arrayOfStrings[i] = malloc(len * sizeof(char));
}
printf("hello1\n");
//for(int i = 0; i < numNumbers; i++){
// fscanf(fp2, "%s", (arrayOfStrings[i]));
//}
fclose(fp2);
// for(int i = 0; i < numNumbers; i++){
// fprintf(stdout, "%s", arrayOfStrings[i]);
// }
return 0;
}
(I'm very new to C, so please go easy on me!)
In C, strings are terminated with a '0' byte, so it looks like your malloc for each string is 1 character too short -- you've only allowed space for the text.
In addition, you mean the count for the size of each line to be a while loop, not an if statement - right now you are counting each line as length "1".
Finally, you are reading off the end of the file in your commented out fscanf code because you haven't closed and reopened it.
Assuming you want to split the input to the strings by the newline character, would you please try:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *filename; // filename to read
char **arrayOfStrings = NULL; // array of strings
char line[BUFSIZ]; // line buffer while reading
char *p; // temporal pointer to the input line
int i, num; // counter for lines
FILE *fp; // file pointer to read
if (argc != 2) {
fprintf(stderr, "usage: %s file.txt\n", argv[0]);
return EXIT_FAILURE;
}
filename = argv[1];
if (NULL == (fp = fopen(filename, "r"))) {
perror(filename);
return EXIT_FAILURE;
}
// read the input file line by line
while (fgets(line, BUFSIZ, fp)) {
if ((p = strrchr(line, '\n'))) *p = '\0'; // remove trailing newline, if any
if ((p = strrchr(line, '\r'))) *p = '\0'; // remove trailing cr character, if any
if (NULL == (arrayOfStrings = realloc(arrayOfStrings, (num + 1) * sizeof(char **)))) {
// enlarge the array according to the line count
perror("realloc");
return EXIT_FAILURE;
}
if (NULL == (arrayOfStrings[num] = malloc(strlen(line) + 1))) {
// memory for the string of the line
perror("malloc");
return EXIT_FAILURE;
}
strcpy(arrayOfStrings[num], line);
num++;
}
// print the strings in the array
for (i = 0; i < num; i++) {
printf("%d %s\n", i, arrayOfStrings[i]);
}
fclose(fp);
return 0;
}
If the input file looks something like:
This
is
the
input.
Then the output will be:
0 This
1 is
2 the
3 input.

Find number of occurrences for the substring in a string using C programming

I am trying a program in c to read a text file that contains array of characters or a string and find the number of occurrences of the substring called "GLROX" and say sequence found when it is found. And the "inputGLORX.txt" contains following string inside it.
GLAAAROBBBBBBXGLROXGLROXGLROXGLROXGLCCCCCCCCCCCCCCROXGGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROX
But i am getting wierd results. It would be great if some expert in C-programming helps me to solve this and thanks in advance.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define NUMBER_OF_STRINGS 40
#define MAX_STRING_SIZE 7
void seqFound()
{
printf("Sequence Found\n");
}
int main()
{
FILE *fp;
char buff[1000];
char strptrArr[NUMBER_OF_STRINGS] [MAX_STRING_SIZE];
const char *search = "GLROX";
fp = fopen("D:/CandC++/inputGLORX.txt", "r");
if(fp==NULL)
printf("It is a null pointer");
while(!feof(fp))
{
//fscanf(fp, "%s", buff);
fgets(buff, 1000,fp);
}
int len = strlen(buff);
printf("length is %d\n",len);
int count = 0;
char *store;
while(store = strstr(buff, search))
{
printf("substring is %s \n",store);
count++;
search++;
}
printf("count is %d\n",count);
while (count!=0) {
seqFound();
count--;
}
return 0;
}
As said in the comment, their are at least 2 problems in the code: your fgets will only fetch the last line (if it fetch one at all ? In any case, this is not what you want), and you are incrementing the search string instead of the buff string.
Something like this should fix most of your problems, as long as no lines in your file are longer than 999 characters. This will not work properly if you use the \n or NULL characters in your search string.
int count = 0;
while (fgets(buff, 1000, fp) != NULL)
{
char *temp = buff;
while ((temp = strstr(temp, search)))
{
printf("%d. %s\n", count + 1, temp);
count++;
temp++;
}
}
Here is a main for testing. I used argv to provide the input.txt and the search string.
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *fp;
char buff[1000];
char *search;
if (argc < 3)
return (-1);
search = argv[2];
if (search[0] == '\0')
return (-1);
if ((fp = fopen(argv[1], "r")) == NULL)
return (-1);
int count = 0;
while (fgets(buff, 1000, fp) != NULL)
{
char *temp = buff;
while ((temp = strstr(temp, search)))
{
printf("%d. %s\n", count + 1, temp);
count++;
temp++;
}
}
printf("Match found: %d\n", count);
return 0;
}
The way you search in buff is wrong, i.e. this code:
while(store = strstr(buff, search))
{
printf("substring is %s \n",store);
count++;
search++; // <------- ups
}
When you have a hit, you change search, i.e. the string you are looking for. That's not what you want. The search string (aka the needle) shall be the same all the time. Instead you want to move forward in the buffer buff so that you can search in the remainder of the buffer.
That could be something like:
int main()
{
const char* buff = "GLAAAROBBBBBBXGLROXGLROXGLROXGLROXGLCCCCCCCCCCCCCCROXGGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROX";
const char* search = "GLROX";
const char* remBuff = buff; // Pointer to the remainder of buff
// Initialized to be the whole buffer
const char* hit;
int cnt = 0;
while((hit = strstr(remBuff, search))) // Search in the remainder of buff
{
++cnt;
remBuff = hit + 1; // Update the remainder pointer so it points just 1 char
// after the current hit
}
printf("Found substring %d times\n", cnt);
return 0;
}
Output:
Found substring 15 times

How to store text, line by line, to a 2D array in C?

again. I'm new to C. Still thinking in Python terms (readlines, append them to variable) so I'm having difficulties translating that to C. This is what I want to do: open a text file for reading, store each line in an array row by row, print it out to make sure it's stored.
This is how far I've got:
int main(){
FILE * fp = fopen("sometext.txt", "r");
char text[100][100];
if(fp == NULL){
printf("File not found!");
}
else{
char aLine[20];
int row = 0;
while(fgets(aLine, 20, fp) != NULL){
printf("%s", aLine);
//strcpy(text[row], aLine); Trying to append a line (as row)
return 0;
}
Please don't start with "invest in some more time and look somewhere else because it's easy and has been answered". I'm bad at this, and I'm trying.
You can try this. Basically you need an array of arrays to store each line. You find the length of the longest line in the file and you allocate space for it. Then rewind the pointer to the start of the file and use fgets to get each line from the file and strdup to allocate space and copy the line to the respective position. Hope this helps.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE * fp = fopen("sometext.txt", "r");
int maxLineSize = 0, count = 0;
char c;
while ((c = fgetc(fp)) != EOF) {
if (c == '\n' && count > maxLineSize) maxLineSize = count;
if (c == '\n') count = 0;
count++;
}
rewind(fp);
char ** lines = NULL;
char * line = calloc(maxLineSize, sizeof(char));
for (int i = 0 ; fgets(line, maxLineSize + 1, fp) != NULL ; i++) { // +1 for \0
lines = realloc(lines, (i + 1) * sizeof(char *));
line[strcspn(line, "\n")] = 0; // optional if you want to cut \n from the end of the line
lines[i] = strdup(line);
printf("%s\n", lines[i]);
memset(line, maxLineSize, '\0');
}
fclose(fp);
}
You could solve it without copy
The follow code could work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
int main()
{
FILE * fp = fopen("sometext.txt", "r");
if(fp == NULL){
printf("File not found!");
return -1;
}
char text[100][20];
int row = 0;
while(row < 100 && fgets(text[row], sizeof(text[0]), fp) != NULL)
++row;
for (int i= 0; i != row; ++i)
fputs(text[i], stdout);
return 0;
}

Lowercase to uppercase with opening new file

I tried to change all random lowercase letters to uppercase letters in this program.First of all, I have initialized in lowercase.txt AkfsASlkALfdk.Then I read from it and changing all the lowercase letters into capital ones.The problem is,when I opened the capital.txt is ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌAKFSASLKALFDK.Where did the error come from?I couldn't find it yet and I decided to ask you.
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <conio.h>
int main()
{
int i;
char s[100];
char k[100];
FILE *kp;
kp = fopen("lowercase.txt", "r");
if (kp == NULL)
{
printf("Error in opening file.\n");
system("pause");
exit(1);
}
FILE *temp;
temp = fopen("capital.txt", "w");
if (kp == NULL)
{
printf("Error in opening file.\n");
system("pause");
exit(2);
}
printf("Opening file is successful.\n");
if (fscanf(kp, "%s", &s) != EOF)
{
for (i = 0; i < 100; i++)
{
if (s[i] >= 97 && s[i] <= 122)
{
s[i] -= 32;
}
}
}
fprintf(temp, "%s", k);
getch();
return 0;
}
Multiple issues in your code which together cause the issues
You are storing the opened FILE* in temp, but checking kp. I think that is because you copy pasted the check from above. Can be easily fixed by changing the variable
You perform the capitalization operation outside what was set by scanf. As suggested by #MOehm, change the loop condition to s[i]
Finally you are converting the string in place in s but are saving k in the file. k is never modified. Change fprintf(temp, "%s", k); to fprintf(temp, "%s", s);
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char *append(const char *s, char c) {
int len = strlen(s);
char buf[len+2];
strcpy(buf, s);
buf[len] = c;
buf[len + 1] = 0;
return strdup(buf);
}
int main(int argc, char **argv)
{
char ch;
FILE *fp;
if (argc != 2)
return (0);
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
char *res;
while((ch = fgetc(fp)) != EOF)
{
res = append(res, ch);
}
fclose(fp);
int i = 0;
while (i < strlen(res))
{
if (res[i] >= 97 && res[i] <= 122)
res[i] = res[i] - 32;
i++;
}
printf("%s\n", res);
return 0;
}
here is a quick example
read the file char by char and add each char in a char *. Then for each character lowercase char, sub 32 to get the uppercase char and write it then print. Give the filename as first parameter when you start the programm

Read from a text file and use each line to compare if they are anagrams

I must modify my program to accept input from
a file called anagrams.txt.This file should have two strings per line, separated by the # character. My program should read
each pair of strings and report back if each pair of strings is an anagram. For example consider the following content of anagrams.txt:
hello#elloh
man#nam
Astro#Oastrrasd
Your program should print out the following:
hello#elloh - Anagrams!
man#nam - Anagrams!
Astro#Oastrrasd- Not anagrams!
I should compile in g++
Here is the code to read from text:
int main()
{
char input[30];
if(access( "anagrams.txt", F_OK ) != -1) {
FILE *ptr_file;
char buf[1000];
ptr_file =fopen("anagrams.txt","r"); if (!ptr_file)
return 1;
while (fgets(buf,1000, ptr_file)!=NULL)
printf("%s",buf);
fclose(ptr_file);
printf("\n");
}
else{ //if file does not exist
printf("\nFile not found!\n");
}
return 0;
}
Code to find if the text are anagrams:
#include <stdio.h>
int find_anagram(char [], char []);
int main()
{
char array1[100], array2[100];
int flag;
printf("Enter the string\n");
gets(array1);
printf("Enter another string\n");
gets(array2);
flag = find_anagram(array1, array2);
if (flag == 1)
printf(" %s and %s are anagrams.\n", array1, array2);
else
printf("%s and %s are not anagrams.\n", array1, array2);
return 0;
}
int find_anagram(char array1[], char array2[])
{
int num1[26] = {0}, num2[26] = {0}, i = 0;
while (array1[i] != '\0')
{
num1[array1[i] - 'a']++;
i++;
}
i = 0;
while (array2[i] != '\0')
{
num2[array2[i] -'a']++;
i++;
}
for (i = 0; i < 26; i++)
{
if (num1[i] != num2[i])
return 0;
}
return 1;
}
You can try something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXLINE 1000
#define MAXLETTER 256
int is_anagram(char *word1, char *word2);
void check_lines(FILE *filename);
int cmpfunc(const void *a, const void *b);
void convert_to_lowercase(char *word);
int
main(int argc, char const *argv[]) {
FILE *filename;
if ((filename = fopen("anagram.txt", "r")) == NULL) {
fprintf(stderr, "Error opening file\n");
exit(EXIT_FAILURE);
}
check_lines(filename);
fclose(filename);
return 0;
}
void
check_lines(FILE *filename) {
char line[MAXLINE];
char *word1, *word2, *copy1, *copy2;
while (fgets(line, MAXLINE, filename) != NULL) {
word1 = strtok(line, "#");
word2 = strtok(NULL, "\n");
copy1 = strdup(word1);
copy2 = strdup(word2);
convert_to_lowercase(copy1);
convert_to_lowercase(copy2);
if (is_anagram(copy1, copy2)) {
printf("%s#%s - Anagrams!\n", word1, word2);
} else {
printf("%s#%s - Not Anagrams!\n", word1, word2);
}
}
}
void
convert_to_lowercase(char *word) {
int i;
for (i = 0; word[i] != '\0'; i++) {
word[i] = tolower(word[i]);
}
}
int
is_anagram(char *word1, char *word2) {
qsort(word1, strlen(word1), sizeof(*word1), cmpfunc);
qsort(word2, strlen(word2), sizeof(*word2), cmpfunc);
if (strcmp(word1, word2) == 0) {
return 1;
}
return 0;
}
int
cmpfunc(const void *a, const void *b) {
if ((*(char*)a) < (*(char*)b)) {
return -1;
}
if ((*(char*)a) > (*(char*)b)) {
return +1;
}
return 0;
}
Since this looks like a University question, I won't provide a full solution, only a hint.
All you have to do is replace the stdin input part of the anagram-finding file with the code you wrote to read from a file: it's as simple as changing
printf("Enter the string\n");
gets(array1);
printf("Enter another string\n");
gets(array2);
to
// before program:
#define SIZE 1000
// inside main
if (access("anagrams.txt", F_OK) == -1){
printf("\nFile not found!\n");
return 1; // Abort the program early if we can't find the file
}
FILE *ptr_file;
char buf[1000];
ptr_file = fopen("anagrams.txt","r");
if (!ptr_file)
return 1;
char array1[SIZE], array2[SIZE];
while (fgets(buf, 1000, ptr_file)!=NULL){
// do all your anagram stuff here!
// there is currently one line of the input file stored in buf
// Hint: You need to split buf into array_1 and array_2 using '#' to separate it.
}
fclose(ptr_file);
printf("\n");
Additional comments:
Don't ever ever ever use gets. gets doesn't check that the string it writes to can hold the data, which will cause your program to crash if it gets input bigger than the array size. Use fgets(buf, BUF_SIZE, stdin) instead.
Beautiful code is good code. People are more likely to help if they can read your code easily. (fix your brackets)
Just for interest, a more efficient algorithm for checking anagrams is to use qsort to sort both arrays, then a simple string matcher to compare them. This will have cost O(mnlog(m+n)), as opposed to O(m^2 n^2), awith the current algorithm
You need to split every line you read by fgets (as you did) in to two strings, and pass them to your find_anagram function. You can do that using strtok:
int main()
{
int flag;
char buf[1000];
FILE *ptr_file;
//Check file existence
//Open the file for reading
while (fgets (buf, 1000, ptr_file) != NULL)
{
char *array1 = strtok(buf, "#");
char *array2 = strtok(NULL, "\n");
flag = find_anagram (array1, array2);
//Check flag value to print your message
}
return 0;
}
//put your find_anagram function
Don't forget to #include <string.h> to use strtok().

Resources