I know how to loop through a file line by line by reading into a FILE* using fopen, fgets etc
but how can i look through a char array line by line using plain C?
i have googled a lot an can only find stuff that reads from a file.
#include <stdio.h>
char *sgets(char *s, int n, const char **strp){
if(**strp == '\0')return NULL;
int i;
for(i=0;i<n-1;++i, ++(*strp)){
s[i] = **strp;
if(**strp == '\0')
break;
if(**strp == '\n'){
s[i+1]='\0';
++(*strp);
break;
}
}
if(i==n-1)
s[i] = '\0';
return s;
}
int main(){
const char *data = "abc\nefg\nhhh\nij";
char buff[16];
const char **p = &data;
while(NULL!=sgets(buff, sizeof(buff), p))
printf("%s", buff);
return 0;
}
Reading a character array line by line : What does a line mean ? '\n' Perhaps.
so, iterate through the array.
int main()
{ char array[10]="ab\nbc\ncd\n";
int lines =0;int i=0;
while(array[i]!='\0')
{ if(array[i]!='\n')
printf("%c",array[i++]);
else { lines++;i++; printf("\n"); }
} return 0;
}
In case if you want to keep your separator flexible (e.g. you got "\r\n") and stick to libraries, strtok is handy:
#include <cstring>
int main() {
const char separator[3] = "\r\n";
char text[13] = "ab\r\ncd\r\nef\r\n";
char *line = NULL;
line = strtok(text, separator);
while (line != NULL) {
printf("%s\n", line); // call your function to process line
line = strtok(NULL, separator); // NULL means continue from where the previous successful call to strtok ended
}
system("pause"); // just prevent console from closing
}
Related
I solved this problem by using realloc(), which is more brief and easier to understand.
Though using malloc() is taking detour, it still helps to enhance my coding logic.
Below is the realloc() version.
char* getInput(char* inputStr)
{
int count = 1;
char *ch;
do{
count++;
fgets(ch, 2, stdin); //ch stores 1 char from user each time
inputStr = realloc(inputStr, (count+1)* sizeof(char));
strcat(inputStr, ch);
printf("in do inputStr=%s\n", inputStr);
}while(ch[0] != '\n');
inputStr[count] = '\0';
printf("in while inputStr=%s\n", inputStr);
return inputStr;
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Original question:
I'm new to C, and I'm in trouble with malloc function.
In my program, the user need to input a arbitrary long string, if there exists a space in the string, then string variable command will take the first part of the input string, variable filename will take the second part. e.g:
Input- read mydiary.txt
inputStr's data is read, command's data is mydiary.txt
I wrote a separate getComd.c file, the command will just take the first part of the inputStr, however, when I put functions getComd together with getInput, getComd will copy the whole getInput string, with the extra filename.
I've put some printf inside the code to help tracing.
I doubt if there is something to do with the variable scope, but I cannot detect the real problem.
Could anyone help me to explain what happened in my code?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* getInput(void);
char* getComd(char* inputStr, char* comd);
int main(){
char* inputStr;
char* command;
char* filename;
printf("Input- ");
inputStr = getInput();
printf("inputStr=%s\n", inputStr);
command = getComd(inputStr, command);
return 0;
}
char* getInput()
{
char* str;
char* _str;
int i = 1; // 1 is for the first char to take;
str = malloc((i+1)*sizeof(char)); // i+1 is for the '\0'
str[i-1] = '\0';
while( '\n' != ( str[i-1] = getchar() ) )
{
i++;
_str = malloc(i*sizeof(char));
strcpy(_str, str);
free(str);
str = malloc((i+1)*sizeof(char));
strcpy(str, _str);
str[i-1] = '\0';
free(_str);
}
return str;
}
char* getComd(char* inputStr, char* comd)
{
comd=NULL;
char* _comd=NULL;
int i = 1; // 1 is to take 1st input char;
comd = malloc((i+1)*sizeof(char)); // i+1 is for the '\0'
printf("enter while loop\n");
while( ( comd[i-1] = inputStr[i-1] ) != ' '){
i++;
_comd = malloc(i*sizeof(char));
strcpy(_comd, comd);
free(comd);
comd = malloc((i+1)*sizeof(char));
strcpy(comd, _comd);
comd[i-1] = '\0';
free(_comd);
printf("comd=%s\n", comd);
}
printf("outside while loop, comd=%s\n", comd);
return comd;
}
Below is the independent getComd.c file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char* inputStr="hello world";
char* comd = NULL;
char* _comd = NULL;
int i = 1; // 1 is for the first char to take;
comd = malloc( (i+1)*sizeof(char) ); // i+1 is for the '\0'
printf("enter while loop\n");
while( ( comd[i-1] = inputStr[i-1] ) != ' '){
i++;
_comd = malloc(i*sizeof(char));
strcpy(_comd, comd);
free(comd);
comd = malloc((i+1)*sizeof(char));
strcpy(comd, _comd);
comd[i-1] = '\0';
free(_comd);
printf("comd=%s\n", comd);
}
printf("outside the while, comd=%s\n", comd);
return 0;
}
So I am trying to read input from a text file and print the exact same thing I read in C.So this below is the input followed by enter:
input: Hi
output: Hi
#include <stdio.h>
#include <stdlib.h>
char *inputString(FILE *fp, size_t size) {
//The size is extended by the input with the value of the provisional
char *str;
int ch;
size_t len = 0;
str = realloc(NULL, sizeof(char) * size); //size is start size
if (!str)
return str;
while (EOF != (ch = fgetc(fp)) && ch != '\n') {
str[len++] = ch;
if (len == size) {
str = realloc(str, sizeof(char) * (size += 16));
if (!str)
return str;
}
}
str[len++] = '\0';
return realloc(str, sizeof(char) * len);
}
int main(void) {
char *m;
// printf("input string : ");
m = inputString(stdin, 10);
printf("%s\n", m);
free(m);
return 0;
}
For this input:
Hi, this is the first line
This is the second line
This is the third line \n
This is the output I expected:
Hi, this is the first line
This is the second line
This is the third line \n
This is what I got:
Hi, this is the first line
It makes sense that the code is printing only the first line, but since the condition in the guard will no longer be true after hitting the new line, but I don't know how to structure my code so it reads line by line and prints them respectively.
If you want the code to read each line, remove && ch != '\n' from the condition of the while loop.
Also, the code is reading from stdin instead of a file. Use fopen to read from a file, i.e. m = inputString(fopen("filename.txt", "r"), 512).
Try this,
#include<stdio.h>
void main(int argc, char **argv)
{
int cnt=0;
char buf[1024];
FILE *fptr=stdin;
printf("Input: \n");
char ch=fgetc(fptr);
buf[cnt++]=ch;
while(ch!='$')
{
buf[cnt++]=ch;
ch=fgetc(fptr);
}
buf[cnt++]='$';
buf[cnt]='\0';
printf("Output:\n");
fputs(buf,stdout);
fclose(fptr);
}
I have put '$' as the delimiter.
I have used an extra buffer as newline is bound to EOF for stdin. So if I print out the character immediately it comes out of loop.
All you need is repeat the process as long as you can read lines:
int main(void) {
char *m;
// printf("input strings: ");
while ((m = inputString(stdin, 10)) != NULL) {
printf("%s\n", m);
free(m);
}
return 0;
}
For this to work correctly, you must return NULL at end of file:
#include <stdio.h>
#include <stdlib.h>
char *inputString(FILE *fp, size_t size) {
//The size is extended by the input with the value of the provisional
int ch;
size_t len = 0;
char *str = malloc(size);
if (str == NULL)
return NULL;
while ((ch = fgetc(fp)) != EOF && c != '\n') {
if (len + 2 > size) {
char *new_str = realloc(str, size += 16);
if (!new_str) {
free(str);
return NULL;
str = new_str;
}
str[len++] = ch;
}
if (c == EOF && len == 0) {
/* at end of file */
free(str);
return NULL;
}
str[len++] = '\0';
return realloc(str, len);
}
Instead of:
while(EOF!=(ch=fgetc(fp))&& ch != '\n' ){
// stuff
}
you could do:
while(EOF!=(ch=fgetc(fp))){
// stuff
if (ch == '\n') break;
}
Now you have consumed the newline.
I want to write a program in C that displays each word of a whole sentence (taken as input) at a seperate line. This is what I have done so far:
void manipulate(char *buffer);
int get_words(char *buffer);
int main(){
char buff[100];
printf("sizeof %d\nstrlen %d\n", sizeof(buff), strlen(buff)); // Debugging reasons
bzero(buff, sizeof(buff));
printf("Give me the text:\n");
fgets(buff, sizeof(buff), stdin);
manipulate(buff);
return 0;
}
int get_words(char *buffer){ // Function that gets the word count, by counting the spaces.
int count;
int wordcount = 0;
char ch;
for (count = 0; count < strlen(buffer); count ++){
ch = buffer[count];
if((isblank(ch)) || (buffer[count] == '\0')){ // if the character is blank, or null byte add 1 to the wordcounter
wordcount += 1;
}
}
printf("%d\n\n", wordcount);
return wordcount;
}
void manipulate(char *buffer){
int words = get_words(buffer);
char *newbuff[words];
char *ptr;
int count = 0;
int count2 = 0;
char ch = '\n';
ptr = buffer;
bzero(newbuff, sizeof(newbuff));
for (count = 0; count < 100; count ++){
ch = buffer[count];
if (isblank(ch) || buffer[count] == '\0'){
buffer[count] = '\0';
if((newbuff[count2] = (char *)malloc(strlen(buffer))) == NULL) {
printf("MALLOC ERROR!\n");
exit(-1);
}
strcpy(newbuff[count2], ptr);
printf("\n%s\n",newbuff[count2]);
ptr = &buffer[count + 1];
count2 ++;
}
}
}
Although the output is what I want, I have really many black spaces after the final word displayed, and the malloc() returns NULL so the MALLOC ERROR! is displayed in the end.
I can understand that there is a mistake at my malloc() implementation, but I do not know what it is.
Is there another more elegant or generally better way to do it?
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
Take a look at this, and use whitespace characters as the delimiter. If you need more hints let me know.
From the website:
char * strtok ( char * str, const char * delimiters );
On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.
Once the terminating null character of str is found in a call to strtok, all subsequent calls to this function (with a null pointer as the first argument) return a null pointer.
Parameters
str
C string to truncate.
Notice that this string is modified by being broken into smaller strings (tokens).
Alternativelly [sic], a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
delimiters
C string containing the delimiter characters.
These may vary from one call to another.
Return Value
A pointer to the last token found in string.
A null pointer is returned if there are no tokens left to retrieve.
Example
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
For the fun of it here's an implementation based on the callback approach:
const char* find(const char* s,
const char* e,
int (*pred)(char))
{
while( s != e && !pred(*s) ) ++s;
return s;
}
void split_on_ws(const char* s,
const char* e,
void (*callback)(const char*, const char*))
{
const char* p = s;
while( s != e ) {
s = find(s, e, isspace);
callback(p, s);
p = s = find(s, e, isnotspace);
}
}
void handle_word(const char* s, const char* e)
{
// handle the word that starts at s and ends at e
}
int main()
{
split_on_ws(some_str, some_str + strlen(some_str), handle_word);
}
malloc(0) may (optionally) return NULL, depending on the implementation. Do you realize why you may be calling malloc(0)? Or more precisely, do you see where you are reading and writing beyond the size of your arrays?
Consider using strtok_r, as others have suggested, or something like:
void printWords(const char *string) {
// Make a local copy of the string that we can manipulate.
char * const copy = strdup(string);
char *space = copy;
// Find the next space in the string, and replace it with a newline.
while (space = strchr(space,' ')) *space = '\n';
// There are no more spaces in the string; print out our modified copy.
printf("%s\n", copy);
// Free our local copy
free(copy);
}
Something going wrong is get_words() always returning one less than the actual word count, so eventually you attempt to:
char *newbuff[words]; /* Words is one less than the actual number,
so this is declared to be too small. */
newbuff[count2] = (char *)malloc(strlen(buffer))
count2, eventually, is always one more than the number of elements you've declared for newbuff[]. Why malloc() isn't returning a valid ptr, though, I don't know.
You should be malloc'ing strlen(ptr), not strlen(buf). Also, your count2 should be limited to the number of words. When you get to the end of your string, you continue going over the zeros in your buffer and adding zero size strings to your array.
Just as an idea of a different style of string manipulation in C, here's an example which does not modify the source string, and does not use malloc. To find spaces I use the libc function strpbrk.
int print_words(const char *string, FILE *f)
{
static const char space_characters[] = " \t";
const char *next_space;
// Find the next space in the string
//
while ((next_space = strpbrk(string, space_characters)))
{
const char *p;
// If there are non-space characters between what we found
// and what we started from, print them.
//
if (next_space != string)
{
for (p=string; p<next_space; p++)
{
if(fputc(*p, f) == EOF)
{
return -1;
}
}
// Print a newline
//
if (fputc('\n', f) == EOF)
{
return -1;
}
}
// Advance next_space until we hit a non-space character
//
while (*next_space && strchr(space_characters, *next_space))
{
next_space++;
}
// Advance the string
//
string = next_space;
}
// Handle the case where there are no spaces left in the string
//
if (*string)
{
if (fprintf(f, "%s\n", string) < 0)
{
return -1;
}
}
return 0;
}
you can scan the char array looking for the token if you found it just print new line else print the char.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
int len = strlen(s);
char delim =' ';
for(int i = 0; i < len; i++) {
if(s[i] == delim) {
printf("\n");
}
else {
printf("%c", s[i]);
}
}
free(s);
return 0;
}
char arr[50];
gets(arr);
int c=0,i,l;
l=strlen(arr);
for(i=0;i<l;i++){
if(arr[i]==32){
printf("\n");
}
else
printf("%c",arr[i]);
}
My code is as follows. I am using a struct and taking in an input text file. I separate it into lines, then attempt to separate each line into its individual words. Using strtok, it is currently only printing the first word of each line. How can I fix this?
typedef struct {
char linewords[101];
char separateword[101];
} line;
The following is in main:
line linenum[101];
char var[101]
char *strtok(char *str, const char delim);
while fgets(linenum[i].linewords, 101, stdin) != NULL) {
char* strcopy();
char* strtok();
strcpy(linenum[i].separateword,linenum[i].linewords);
strtok(linenum[i].separateword, " "); /*line i'm referring to*/
i++;
}
}
I apologise in advance for any confusion. What I want is to have it so linenum[i].separateword[0] will return the first word, etc. Is this possible? Or is there another way of splitting my input into words?
Thank you
#include <stdio.h>
#include <string.h>
typedef struct {
char linewords[101];
char *separateword[51];
} line;
int main(void){
line linenum[101];
int i = 0;
while(fgets(linenum[i].linewords, sizeof(linenum[i].linewords), stdin) != NULL) {
char *token, *delm = " \t\n";
int j = 0;
for(token = strtok(linenum[i].linewords, delm);
token;
token = strtok(NULL, delm)){
linenum[i].separateword[j++] = token;
}
linenum[i++].separateword[j] = NULL;
}
{//test print
char **p = linenum[0].separateword;
while(*p)
puts(*p++);
}
return 0;
}
I want to write a program in C that displays each word of a whole sentence (taken as input) at a seperate line. This is what I have done so far:
void manipulate(char *buffer);
int get_words(char *buffer);
int main(){
char buff[100];
printf("sizeof %d\nstrlen %d\n", sizeof(buff), strlen(buff)); // Debugging reasons
bzero(buff, sizeof(buff));
printf("Give me the text:\n");
fgets(buff, sizeof(buff), stdin);
manipulate(buff);
return 0;
}
int get_words(char *buffer){ // Function that gets the word count, by counting the spaces.
int count;
int wordcount = 0;
char ch;
for (count = 0; count < strlen(buffer); count ++){
ch = buffer[count];
if((isblank(ch)) || (buffer[count] == '\0')){ // if the character is blank, or null byte add 1 to the wordcounter
wordcount += 1;
}
}
printf("%d\n\n", wordcount);
return wordcount;
}
void manipulate(char *buffer){
int words = get_words(buffer);
char *newbuff[words];
char *ptr;
int count = 0;
int count2 = 0;
char ch = '\n';
ptr = buffer;
bzero(newbuff, sizeof(newbuff));
for (count = 0; count < 100; count ++){
ch = buffer[count];
if (isblank(ch) || buffer[count] == '\0'){
buffer[count] = '\0';
if((newbuff[count2] = (char *)malloc(strlen(buffer))) == NULL) {
printf("MALLOC ERROR!\n");
exit(-1);
}
strcpy(newbuff[count2], ptr);
printf("\n%s\n",newbuff[count2]);
ptr = &buffer[count + 1];
count2 ++;
}
}
}
Although the output is what I want, I have really many black spaces after the final word displayed, and the malloc() returns NULL so the MALLOC ERROR! is displayed in the end.
I can understand that there is a mistake at my malloc() implementation, but I do not know what it is.
Is there another more elegant or generally better way to do it?
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
Take a look at this, and use whitespace characters as the delimiter. If you need more hints let me know.
From the website:
char * strtok ( char * str, const char * delimiters );
On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.
Once the terminating null character of str is found in a call to strtok, all subsequent calls to this function (with a null pointer as the first argument) return a null pointer.
Parameters
str
C string to truncate.
Notice that this string is modified by being broken into smaller strings (tokens).
Alternativelly [sic], a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
delimiters
C string containing the delimiter characters.
These may vary from one call to another.
Return Value
A pointer to the last token found in string.
A null pointer is returned if there are no tokens left to retrieve.
Example
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
For the fun of it here's an implementation based on the callback approach:
const char* find(const char* s,
const char* e,
int (*pred)(char))
{
while( s != e && !pred(*s) ) ++s;
return s;
}
void split_on_ws(const char* s,
const char* e,
void (*callback)(const char*, const char*))
{
const char* p = s;
while( s != e ) {
s = find(s, e, isspace);
callback(p, s);
p = s = find(s, e, isnotspace);
}
}
void handle_word(const char* s, const char* e)
{
// handle the word that starts at s and ends at e
}
int main()
{
split_on_ws(some_str, some_str + strlen(some_str), handle_word);
}
malloc(0) may (optionally) return NULL, depending on the implementation. Do you realize why you may be calling malloc(0)? Or more precisely, do you see where you are reading and writing beyond the size of your arrays?
Consider using strtok_r, as others have suggested, or something like:
void printWords(const char *string) {
// Make a local copy of the string that we can manipulate.
char * const copy = strdup(string);
char *space = copy;
// Find the next space in the string, and replace it with a newline.
while (space = strchr(space,' ')) *space = '\n';
// There are no more spaces in the string; print out our modified copy.
printf("%s\n", copy);
// Free our local copy
free(copy);
}
Something going wrong is get_words() always returning one less than the actual word count, so eventually you attempt to:
char *newbuff[words]; /* Words is one less than the actual number,
so this is declared to be too small. */
newbuff[count2] = (char *)malloc(strlen(buffer))
count2, eventually, is always one more than the number of elements you've declared for newbuff[]. Why malloc() isn't returning a valid ptr, though, I don't know.
You should be malloc'ing strlen(ptr), not strlen(buf). Also, your count2 should be limited to the number of words. When you get to the end of your string, you continue going over the zeros in your buffer and adding zero size strings to your array.
Just as an idea of a different style of string manipulation in C, here's an example which does not modify the source string, and does not use malloc. To find spaces I use the libc function strpbrk.
int print_words(const char *string, FILE *f)
{
static const char space_characters[] = " \t";
const char *next_space;
// Find the next space in the string
//
while ((next_space = strpbrk(string, space_characters)))
{
const char *p;
// If there are non-space characters between what we found
// and what we started from, print them.
//
if (next_space != string)
{
for (p=string; p<next_space; p++)
{
if(fputc(*p, f) == EOF)
{
return -1;
}
}
// Print a newline
//
if (fputc('\n', f) == EOF)
{
return -1;
}
}
// Advance next_space until we hit a non-space character
//
while (*next_space && strchr(space_characters, *next_space))
{
next_space++;
}
// Advance the string
//
string = next_space;
}
// Handle the case where there are no spaces left in the string
//
if (*string)
{
if (fprintf(f, "%s\n", string) < 0)
{
return -1;
}
}
return 0;
}
you can scan the char array looking for the token if you found it just print new line else print the char.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
int len = strlen(s);
char delim =' ';
for(int i = 0; i < len; i++) {
if(s[i] == delim) {
printf("\n");
}
else {
printf("%c", s[i]);
}
}
free(s);
return 0;
}
char arr[50];
gets(arr);
int c=0,i,l;
l=strlen(arr);
for(i=0;i<l;i++){
if(arr[i]==32){
printf("\n");
}
else
printf("%c",arr[i]);
}