Splitting a string in a file into array in c - c

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

Related

How to change one string to another with different sizes

I have a task to do. I have to work with strings. I will show you the input and output, because I think that will be clear what the task is.
Input: "aaa bbuvvvvo"
Output: "a$3 b$2uv$4o"
If there is the same symbols, I have to leave that symbol and then put dollar sign '$' and an integer of how many same signs was there. I am stuck on the spot, where I have to change string without losing any information.
I will leave my code here, it might help.
#include <stdio.h>
#include <string.h>
#define CAPACITY 255
#define MAX_NUMBER 10
void Output(char readFile[], char outputFile[], char string[]);
void changeString(char string[], char newString[]);
int main() {
char readFile[CAPACITY];
char outputFile[CAPACITY];
char string[CAPACITY];
// Input file's name
printf("Iveskite teksto failo varda: ");
scanf("%s", &readFile);
// Output file's name
printf("Iveskite teksto faila i kuri bus isvedamas atsakymas: ");
scanf("%s", &outputFile);
Output(readFile, outputFile, string);
return 0;
}
// Scanning file
void Output(char readFile[], char outputFile[], char string[])
{
char newString[CAPACITY];
FILE *input, *output;
input = fopen(readFile, "r");
while(fscanf(input, "%s", string) != EOF)
{
changeString(string, newString);
printf("%s\n", newString);
}
}
// Changing string to wanted string
void changeString(char string[], char newString[])
{
char number[MAX_NUMBER];
int symbols = 0;
int j;
for(int i = 0; string[i] != '\0'; ++i)
{
int temp = i;
newString[i] = string[i];
if(newString[i] == string[i + 1])
{
j = i;
while(string[j] == string[i])
{
++symbols;
++j;
}
// Changing int to char
sprintf(number, "%d", symbols);
newString[i + 1] = '$';
i += 2;
newString[i] = number[0];
symbols = 0;
}
}
}
I have tried to do that with function called changeString, but I get the wrong output all the time. Also the input I am getting is from .txt file.
EDIT: When I compiling this program right now, I get a$3 b$2v$4vo that output.
For starters this declaration in main
char string[CAPACITY];
does not make sense.
You should declare variables in scopes where they are used.
The variable string is used in the function Output where it is should be declared.
The function changeString should be declared like
void changeString( const char string[], char newString[]);
because the source string is not changed within the function.
Your function has several bugs.
For example it does not build a string in the array newString because it does not append the stored sequence in the array with the terminating zero character '\0'.
Secondly this increasing of the variable i
i += 2;
in general is invalid. You need to add to the variable i the number of repeated characters in the source string.
Or the number of repeated characters change greater than or equal to 10. In this case this statement
newString[i] = number[0];
will not produce correct result.
The function can be defined the following way as shown in the demonstration program below.
#include <stdio.h>
#define CAPACITY 255
void changeString( const char string[], char newString[] )
{
while ( *string )
{
*newString++ = *string;
size_t n = 1;
while (*++string == *( newString - 1 ) ) ++n;
if (n != 1)
{
*newString++ = '$';
int count = sprintf( newString, "%zu", n );
newString += count;
}
}
*newString = '\0';
}
int main( void )
{
char string[CAPACITY] = "aaa bbuvvvvo";
char newString[CAPACITY];
changeString( string, newString );
puts( newString );
}
The program output is
a$3 b$2uv$4o

Find N letter words in file

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.

C - Recursively reverse string from one file into another file

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.

C - Storing Values from text into Arrays

I'm trying to store different values that are taken from a file line by line. The lines in the text file read as something shown below
100000,player1,long title name
300000,someotherplayer,another long title name
45512845,thisplayer,one more long title name
I want to store each value that is comma separated into three different arrays, (int)number, (str)player_name, (str)title_name.
I have some code below, but it doesn't compile.
ptr_file=fopen("text.txt", "r");
char buffer[1000];
int line;
line = 0;
while(fgets(buffer, sizeof(buffer), ptr_file) != NULL){
char number[line]=strtok(buffer, ",");
char player_name[line]=strtok(NULL, ",");
char title_name[line]=strtrok(NULL, ",");
}
Can someone give me some advice on this?
So, there are a couple of issues with your code,
You open the file in mode "o" which I'm not really sure what it is, I suspect you want "r"
strtok returns a char * which you cannot assign to a char[].
One the second run through the loop you will overwrite the data in buffer.
I would do something like this:
struct player {
int number;
char player_name[64];
char title_name[256];
};
int main(void) {
FILE *ptrfile=fopen("text.txt", "r");
char buffer[1000];
int line;
struct player players[16];
line = 0;
if(ptrfile==NULL) return 0;
while(fgets(buffer, sizeof(buffer), ptrfile) != NULL){
if(strcmp(buffer, "") == 0) return 0;
char *number=strtok(buffer, ",");
char *player_name=strtok(NULL, ",");
char *title_name=strtok(NULL, ",");
players[line].number=atoi(number);
strcpy(players[line].player_name, player_name);
strcpy(players[line].title_name, title_name);;
line++;
}
fclose(ptrfile);
return 0
}
function strtok return a pointer, so it should be
char* p = strtok(...)
Check the reference here
This is something I did that was similar to what you seem to be doing. The problem you will find is that you want to make each value into a char* but you have to malloc each one then you can connect this char* into the array. It would also just be easier to do that with the numbers to then turn them into int later on.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *msg[100];
char temp[100];
int length, i;
int num = 0;
while((scanf("%s", &temp[0]) != EOF))
{
length = strlen(temp);
msg[num] = malloc((length+1 )* sizeof(char));
strcpy(msg[num], temp);
num++;
}
printf("There are %d words in the this input.\n", num);
for(i = 0; i < num; i++)
{
printf("%s\n", msg[i]);
}
return 0;
}
The thing with the malloc is that you will have to have each one unique because the words are all different sizes. I know this example isn't exactly what your doing but it will get you in the right direction.

How to remove a carriage return from a string in C? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Remove characters from a string in C
Do you have an example of C code to remove carriage returns in a string?
The simplest solution is to probably just process the string character by character, with pointers for source and destination:
#include <stdio.h>
#include <string.h>
int main (void) {
char str[] = "This is a two-line\r\nstring with DOS line endings.\r\n";
printf("%d [%s]\n",strlen(str), str);
// ========================
// Relevant code in this section.
char *src, *dst;
for (src = dst = str; *src != '\0'; src++) {
*dst = *src;
if (*dst != '\r') dst++;
}
*dst = '\0';
// ========================
printf("%d [%s]\n",strlen(str), str);
}
This sets up two pointers initially the same. It then copies a character and always advances the source pointer. However, it only advances the destination pointer if the character wasn't a carriage return. That way, all carriage returns are overwritten by either the next character or the null terminator. The output is:
51 [This is a two-line
string with DOS line endings.
]
49 [This is a two-line
string with DOS line endings.
]
This would be adequate for most strings. If your strings are truly massive in size (or this is something you need to do many times each second), you could look at a strchr-based solution since the library function will most likely be optimised.
A carriage return or any other char is easy to replace in a string and even easier to replace. Your question does not really shows what you're looking for so I've included sample code for both removing and replacing a char in a string.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void remove_char_from_string(char c, char *str)
{
int i=0;
int len = strlen(str)+1;
for(i=0; i<len; i++)
{
if(str[i] == c)
{
// Move all the char following the char "c" by one to the left.
strncpy(&str[i],&str[i+1],len-i);
}
}
}
void replace_char_from_string(char from, char to, char *str)
{
int i = 0;
int len = strlen(str)+1;
for(i=0; i<len; i++)
{
if(str[i] == from)
{
str[i] = to;
}
}
}
int main(void) {
char *original = "a\nmultiline\nstring";
int original_len = strlen(original)+1;
char *string = (char *)malloc(original_len);
memset(string,0,original_len);
strncpy(string,original,original_len);
replace_char_from_string('\n',' ',string);
printf("String: %s\n",string); // print: String: a multiline string
remove_char_from_string(' ',string);
printf("String: %s\n",string); // print: String: amultilinestring
return 0;
}

Resources