Splitting a string (Segmentation Fault on test) - c

I'm trying to extract a substring from a giving input,
for example if i have : "Hello I am here" in a char *
I want to get :
char tab[0] = "Hello";
char tab[1] = "I";
/// etc
But it gives me a Segfault, any help ?
Here is my function to divide my char * :
#include <stdlib.h>
char **str_to_wordtab(char *str)
{
int i;
int j;
int k;
char **tab;
i = 0;
k = 0;
tab = malloc(my_strlen(str) * sizeof(*tab));
while (str[k] != '\0')
{
j = 0;
tab[i] = malloc(my_strlen(str) * sizeof(*tab[i]));
while (str[k] != ' ')
tab[i][j++] = str[k++];
tab[i][j] = '\0';
if (str[k] == ' ')
k++;
i++;
}
return (tab);
}
And here is the main to test it :
int main(int ac, char **av)
{
char **tab;
int i;
i = 0;
tab = str_to_wordtab("Hello I am here");
while (tab[i])
{
my_putstr(tab[i++]);
my_putstr("\n");
}
}
Thanks for helping me.

Your inner while loop should look like this:
while (str[k] != ' ')
{
tab[i][j++] = str[k++];
if (str[k-1] == 0)
{
tab[++i] = 0 ;
return tab ;
}
}

This is not a division that you want but a split of string.
Consider strtok with space as a delimiter.
About your segfault, here are some leads:
while (str[k] != '\0') might be dangerous if you forgot to recopy the \0 in your string
your post-incrementations might be source of errors too

Related

Split a string to an array of strings, along with a flag

I'm trying to write a code in c that return 1 if there is "&" in the string and 0 otherwise.
In addition, the char* that I receive in the function I want to put it in an array of chars and NULL in the end.
My code is like this:
char** isBackslash(char* s1, int *isFlag) {
int count = 0;
isFlag = 0;
char **s2[100];
char *word = strtok(s1, " ");
while (word != NULL) {
s2[count] = word;
if (!strcmp(s2[count], "&")) {
isFlag = 1;
}
count++;
word = strtok(NULL, " ");
}
s2[count] = NULL;
return s2;
}
For example, if the original string (s1) is "Hello I am John &".
So I want s2 to be like:
s2[0] = Hello
s2[1] = I
s2[2] = am
s2[3] = John
s2[4] = &
s2[5] = NULL
And the function will return '1'. What is wrong with my code? I debugged it and unfortunately, I don't find the problem.
You were shadowing your own parameter. See a working example below:
#include <stdio.h>
#include <string.h>
#define BUFF_SIZE 256
int isBackslash(char* s1, char s2[][BUFF_SIZE]) {
int isFlag = 0;
int i = 0;
int j = 0;
int n = 0;
while (s1[i] != '\0') {
isFlag |= !('&' ^ s1[i]); // will set the flag if '&' is met
if (s1[i] == ' ') {
while (s1[i] == ' ')
i++;
s2[n++][j] = '\0';
j = 0;
}
else
s2[n][j++] = s1[i++];
}
return isFlag;
}
int main(void) {
char s2[BUFF_SIZE/2+1][BUFF_SIZE];
memset(s2, 0, sizeof(s2));
char s1[BUFF_SIZE] = "Hello I am John &";
int c = isBackslash(s1, s2);
printf("%d\n", c);
int i = 0;
while (s2[i][0] != '\0')
printf("%s\n", s2[i++]);
}

Reading In txt File and Extracting Elements from Input Problem

I have been attempting to fix this for hours. I am trying to read a file called wiktionary called "stuff.txt" which has input of the form:
10000
5627187200 the
3395006400 of
2994418400 and
2595609600 to
1742063600 in
...
The 10000 represents the number of lines. I am then reading it in using a function read_in_terms, and extracting the number (weight) and the word (word) from it. I have tested my get_word and get_weight functions seperately and they seem to be working. However, when I am reading in, my get_word function is not returning the word .... the get_weight number is...
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* concat(const char *s1, const char *s2) {
char *result = malloc(strlen(s1) + strlen(s2) + 1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
// from a string of the form " 29480398934 the" it returns number
long get_weight(char *string) {
long length = strlen(string);
char number[200];
int count = 0;
// Here I am cycling through until X__X combination
// I only add to the number if it is not " "
for (int i = 0; i < length; i++) {
if (string[i-1] != ' ' && string[i] == ' ' && string[i+1] == ' ' && string[i+1] != ' ') {
break;
} else if (string[i] != ' '){
number[count] = string[i];
count++;
}
}
number[count] = '\0';
return atol(number); // converts it to a long and then returns
}
// from a string of the form " 453495834 word" it returns word
char * get_word(char* string) {
long length = strlen(string);
char word[200];
int count = 0;
// the double space detection only works once we reach a character
// this becomes 1 once that happens, allowing us to proceed to the next part
int blocker = 0;
for (int i = 0; i < length; i++) {
if (string[i] != ' '){
blocker++;
}else if (blocker > 0 && string[i] == ' ' && string[i+1] == ' ') {
int int_count = i+1;
while (string[int_count] != '\0') {
int_count++;
word[count] = string[int_count];
count++;
}
}
}
word[count] = '\0';
// now I need to copy this string into malloc
char *str = (char *)malloc(count*sizeof(char));
strcpy(str, word);
return str;
}
void read_in_terms(int *pnterms, char *filename) {
char part1[] = "/Users/adammartinez/Desktop/";
char* title = concat(part1,filename);
FILE *fp = fopen(title, "r");
char line[200];
fgets(line, sizeof(line), fp);
int num_lines = atoi(line);
for (int i = 0; i < num_lines; i++){
fgets(line, sizeof(line), fp);
printf("%ld \n", get_weight(line));
printf("%s \n", get_word(line)); // NOT RETURNING WORDS
}
}
int main(void) {
//char* test_str = " 547584758475 the";
//printf("%s %ld", get_word(test_str), get_weight(test_str));
int terms = 1000;
int *pointer = &terms;
read_in_terms(pointer, "stuff.txt");
return 0;
}
It seems to work fine on my computer. Please look at the output below and tell me if it's what you're looking for. I set part1 to "" and I changed the number of lines in stuff.txt to 5.
5627187200
the
3395006400
of
2994418400
and
2595609600
to
1742063600
in

Splitting a string to an array of strings

I'm trying to split a sentence the user inputs to an array of words so I can later manipulate the words separately as strings.
The code is compiling but prints only garbage after the user input.
I tried debugging but don't see the problem. Can someone help me fix it?
#include <stdio.h>
#include <string.h>
int main() {
char str[1000];
int i = 0;
char rev[1000][1000];
int r = 0;
puts("Enter text:");
gets(str);
int k, length = 0;
printf_s("So the words are:\n");
while (str[i] != '\0') {
if (str[i] == ' ') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != ' ');
printf(" ");
length = (-1);
r++;
} else
if (str[i + 1] == '\0') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != '\0');
length = 0;
r++;
}
length++;
i++;
}
for (int r = 0; r < 1000; r++)
printf("%s ", rev[r]);
return 0;
}
fix like this
#include <stdio.h>
int main(void) {
char str[1000];
char rev[1000][1000];
puts("Enter text:");
fgets(str, sizeof str, stdin);//Use fgets instead of gets. It has already been abolished.
int r = 0;
int k = 0;
for(int i = 0; str[i] != '\0'; ++i){
if (str[i] == ' ' || str[i] == '\n'){//is delimiter
if(k != 0){
rev[r++][k] = '\0';//add null-terminator and increment rows
k = 0;//reset store position
}
} else {
rev[r][k++] = str[i];
}
}
if(k != 0)//Lastly there was no delimiter
rev[r++][k] = '\0';
puts("So the words are:");
for (int i = 0; i < r; i++){
printf("%s", rev[i]);
if(i < r - 2)
printf(", ");
else if(i == r - 2)
printf(" and ");
}
return 0;
}
Replace you declaration
char rev[1000][1000];
with
char * rev[1000]; // We will need pointers only
int i = 0; // Index to previous array
and all your code after
puts( "Enter text:" );
with this:
fgets( str, 998, stdin ); // Safe way; don't use gets(str)
const char delim[] = ",; "; // Possible delimiters - comma, semicolon, space
char *word;
/* Get the first word */
word = strtok( str, delim );
rev[i++] = word;
/* Get the next words */
while( word != NULL )
{
word = strtok( NULL, delim );
rev[i++] = word;
}
/* Testing */
for (int r = 0; r < i - 1; r++)
printf( "%s\n", rev[r] );
return 0
}
As you can see, all dirty work is done with the strtok() function ("string to tokens") which walks through other and other words ("tokens"), recognizing them as delimited by one or more characters from the string delim.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_spaces(char *str)
{
if (str == NULL || strlen(str) <= 0)
return (0);
int i = 0, count = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return (count);
}
int count_char_from_pos(char *str, int pos)
{
if (str == NULL || strlen(str) <= 0)
return 0;
int i = pos, count = 0;
while (str[i] && str[i] != ' ')
{
count++;
i++;
}
return count;
}
char **get_words(char *str)
{
if (str == NULL || strlen(str) <= 0)
{
printf("Bad string inputed");
return NULL;
}
int i = 0, j = 0, k = 0;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL
|| (dest[0] = malloc(sizeof(char) * (count_char_from_pos(str, 0) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
while (str[i])
{
if (str[i] == ' ') {
dest[j++][k] = '\0';
if ((dest[j] = malloc(sizeof(char) * (count_char_from_pos(str, i) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
k = 0;
}
else {
dest[j][k++] = str[i];
}
i++;
}
dest[j][k] = 0;
dest[j + 1] = NULL;
return dest;
}
int main(void) {
char *line = NULL;
size_t n = 0;
getline(&line, &n, stdin);
printf("%s\n", line);
line[strlen(line) - 1] = 0;
printf("%s\n", line);
char **tab = get_words(line);
int i = 0;
while (tab[i])
{
printf("%s\n", tab[i++]);
}
}
here is a long but fully working example
get the user input
then send it to get_words function. It will get the number of words, the number of characters for each words, allocate everything in memory and writes chars then return it. You get a char ** and prints it just tested it it works
If you wish to split a string into an array of strings, you should consider the strtok function from #include <string.h>. The strtok function will the split the string on the given delimiter(s). For your case, it would the " ".
Using the strtok example from Tutorials Point:
#include <string.h>
#include <stdio.h>
int main(){
char str[80] = "This is - www.tutorialspoint.com - website";//The string you wish to split
const char s[] = "-";//The thing you want it to split from. But there is no need to this.
char *token;//Storing the string
/* get the first token */
token = strtok(str, s);//Split str one time using the delimiter s
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );//Print the string
token = strtok(NULL, s);//Split the string again using the delimiter
}
return(0);
}

Reverse words in C Language

I'm trying to reverse the letters for words in a sentence. I am also trying to store these words in a new char array. At the moment I getting a runtime error, which for all my tweaking I can not solve. My approach is to create a new char array the same length as the sentence. Then loop through the sentence until I reach a ' ' character. Then loop backwards and add these characters to a word. Then add the word to the new Sentence. Any help would be much appreciated.
int main(void) {
char sentence [] = "this is a sentence";
char *newSentence = malloc(strlen(sentence)+1);
int i,j,start;
start = 0;
for(i = 0; i <= strlen(sentence); i++)
{
if(sentence[i] == ' ')
{
char *word = malloc((i - start)+1);
for(j = sentence[i]; j >= start; j--)
{
word[j] = sentence[j];
}
strcat(newSentence,word);
start =sentence[i +1];
}
}
printf("%s",newSentence);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char sentence [] = "this is a sentence";
char *newSentence;
int i,j,start, len;
start = 0;
len = strlen(sentence);
newSentence = malloc(len+1);
*newSentence = '\0';
for(i = 0; i <= len; i++)
{
if(sentence[i] == ' ' || sentence[i] == '\0')
{
char *word = malloc((i - start)+1);
int c = 0;
for(j = i - 1; j >= start; j--)
{
word[c++] = sentence[j];
}
word[c]='\0';
strcat(newSentence,word);
if(sentence[i] == ' ')
strcat(newSentence," ");
start = i + 1;
free(word);
}
}
printf("%s",newSentence);
return 0;
}
Logically, here:
j = sentence[i]
start =sentence[i +1];
start and j are index positions in the char array, you are trying to assign a char to them, which screws everything up.
should be:
j= i;
start = i +1;
if your algorithm is right.
Yet another variant of the same...
int main(int argc, const char *argv[])
{
char sentence [] = "this is a sentence";
size_t len = strlen(sentence);
char *newSentence = malloc(len + 1);
char *ptr_src = sentence;
char *ptr_dst = newSentence;
while(ptr_src)
{
char *next, *t;
next = strchr(ptr_src, ' '); // find next space
if (!next) next = sentence + len; // if not found, next = EOL
for (t = next; t > ptr_src;)
{
*ptr_dst++ = *--t;
}
if (*next)
{
*ptr_dst++ = *next++;
ptr_src = next;
}
else
{
*ptr_dst = 0;
break;
}
}
printf("[%s]",newSentence);
return 0;
}
Your program had few bugs. Which I've tried to remove in this program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char sentence [] = "this is a sentence";
char *newSentence = (char *)malloc(strlen(sentence)+1);
int i,j,start, k;
start = 0;
for(i = 0;; i++)
{
if(sentence[i] == ' ' || sentence[i] == '\0') //sentence[i] == '\0' for the last word.
{
char *word = (char *) malloc((i - start)+1);
for(j = i-1, k = 0; j >= start; j--, k++)
{
word[k] = sentence[j];
}
word[k++] = ' '; //space after each word
word[k] = '\0';
strcat(newSentence,word);
start = i+1;
}
if (sentence[i] == '\0')
break;
}
printf("%s\n",newSentence);
return 0;
}
Check live at http://ideone.com/Z9ogGk
strcat(newSentence,word);
newSentence has to be a string. And a string is a contiguous sequence of characters terminated by and including the first null character
EDIT: this answer has been downvoted 4 times for what is written above. If you think it is incorrect, please explain. Otherwise please remove your downvote.

how to perform reversing a sentence Word by Word in C?

#include <stdio.h>
int main(void)
{
int i,j;
int wordstart = -1;
int wordend = -1;
char words[]= "this is a test";
char temp;
// Reverse each word
for (i = 0; i < strlen(words); ++i)
{
wordstart = -1;
wordend = -1;
if(words[i] != ' ')
wordstart = i;
for (j = wordstart; j < strlen(words); ++j)
{
if(words[j] == ' ')
{
wordend = j - 1;
break;
}
}
if(wordend == -1)
wordend = strlen(words);
for (j = wordstart ; j <= (wordend - wordstart) / 2; ++j)
{
temp = words[j];
words[j] = words[wordend - (j - wordstart)];
words[wordend - (j - wordstart)] = temp;
}
i = wordend;
printf("reversed string is %s:", words);
}
}
I tried in this way but i am getting this output:
siht is a test
my expected output is:
test a is this
I would appreciate if some one could come with a different approach for which time complexity is very less or correct me if it is the right approach. Thanks
Perhaps this belongs on the code review site instead?
Your approach seems very efficient to me (except that I would only call strlen(words) once and save the result in a register).
Two possible bugs look like:
wordend = strlen(words);
should be
wordend = strlen(words)-1;
and
for(j = wordstart ; j <= (wordend - wordstart) / 2 ; ++j) {
should be
for(j = wordstart ; j <= (wordend + wordstart) / 2 ; ++j) {
Final code looks like (with some extra {}):
#include <stdio.h>
int main(int argc,char *argv[])
{
int i,j;
char words[]= "this is a test";
int L=strlen(words);
// Reverse each word
for(i = 0; i < L; ++i) {
int wordstart = -1;
int wordend = -1;
if(words[i] != ' ')
{
wordstart = i;
for(j = wordstart; j < L; ++j) {
if(words[j] == ' ') {
wordend = j - 1;
break;
}
}
if(wordend == -1)
wordend = L-1;
for(j = wordstart ; j <= (wordend + wordstart) / 2 ; ++j) {
char temp = words[j];
words[j] = words[wordend - (j - wordstart)];
words[wordend - (j - wordstart)] = temp;
}
i = wordend;
}
}
printf("reversed string is %s:",words);
return 0;
}
You can create a double linked list as a base data structure. Then, iterate through the words and insert them in the list as you find them.
When you reach the end of the sentence, simply traverse the list backwards and print the words as you go through them
Simply we can just use a n*1 2D character array tailored to suit our needs!!!
#include <stdlib.h>
int main()
{
char s[20][20];
int i=0, length=-1;
for(i=0;;i++)
{
scanf("%s",s[i]);
length++;
if(getchar()=='\n')
break;
}
for(i=length;i>=0;i--)
printf("%s ",s[i]);
return 0;
}
Start tokenizing the line from the last character and continue to the first character. Keep one pointer anchored at the base of the current word, and another pointed which will decrease while a word start is not found. When you find a word start while scanning like this, print from the word start pointer to the word end anchor. Update the word end anchor to the previous character of the current word start char.
You might want to skip the blankspace characters while scanning.
UPDATE
This is a quick implementation:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_BUF 256
void show_string (char *str, int i, int n)
{
while (i <= n)
{
printf ("%c", str[i]);
i++;
}
}
int main (void)
{
char str[MAX_BUF];
int end_anchor, start_ptr;
int state;
printf ("\nEnter a string: ");
scanf (" %[^\n]", str);
start_ptr = strlen (str) - 1;
end_anchor = start_ptr;
state = 0;
while (start_ptr >= -1)
{
switch (state)
{
case 0:
if ((!isspace (str[start_ptr]) && (start_ptr >= 0)))
{
start_ptr--;
}
else
{
state = 1;
}
break;
case 1:
show_string (str, start_ptr + 1, end_anchor);
state = 2;
start_ptr--;
printf (" ");
break;
case 2:
if (!isspace (str[start_ptr]))
{
state = 0;
end_anchor = start_ptr;
}
else
{
start_ptr--;
}
break;
}
}
printf ("\n");
return 0;
}
The end_anchor points to each end word, and the start_ptr finds the start of the word of which the end is held by end_anchor. When we find a word start (by blankspace characters or start_ptr = -1), we print all the characters from start_ptr + 1 to end_anchor. The + 1 is because of the implementation: start_ptr points to the blankspace character, and the print routine will print all the characters from i to n. Once we have detected one blank space we print it and we skip adjacent blankspaces (in case 2) and preserve only one which is manually printed. Once a non blankspace is detected, we have got another word end, for which we set the end_anchor to this index in the case 2, and set state = 0 , so that we can search for the word start again.
if(words[i] != ' ')
wordstart = i;
This statement what about the else part? if words[i] == ' ', and wordstart remains -1.
So maybe try to use:
while (words[i] && words[i] == ' ') ++i;
if (!words[i])
break;
wordstart = i;
Then you should output the result out of the i loop.
Finally, if you want to get the result you expected, you should reverse the whole sentence once more, with the way you used in the loop.
I would use write function similar to strrchr for finding last occurence of ' ', if its found print word that follows, rewrite this ' ' with '\0' and repeat it in loop till no more words are found. At the end I would print the content of this string again because there is most likely no ' ' before the first word.
I would write own function instead of strrchr because strrchr calculates the lenght of the given string, which is redundant in this case. This length doesn't have to be calculated more than once.
Here's the code:
char* findLastWord(char* str, int* len)
{
int i;
for (i = *len - 1; i >= 0; --i)
{
if (str[i] == ' ')
{
str[i] = '\0';
if (i < *len - 1)
{
*len = i - 1;
return &str[i + 1];
}
}
}
return NULL;
}
int main (int argc, char *argv[])
{
char str[] = " one two three four five six ";
int len = strlen(str);
char* lastWord = findLastWord(str, &len);
while (lastWord != NULL)
{
printf("%s\n", lastWord);
lastWord = findLastWord(str, &len);
}
if (len > 1)
printf("%s\n", str);
return 0;
}
output:
six
five
four
three
two
one
Hope this helps ;)
#include<stdio.h>
#include<string.h>
void reverse(char *str, size_t len)
{
char tmp;
size_t beg, end;
if (len <=1) return;
for (beg=0,end=len; beg < --end ; beg++) {
tmp = str[beg];
str[beg] = str[end];
str[end] = tmp;
}
}
int main(void)
{
char sentence[] = "one two three four five";
size_t pos, len;
printf("Before:%s\n",sentence);
for (pos = len= 0; sentence[pos]; pos += len) {
pos += strspn( sentence+pos, " \t\n" );
len = strcspn( sentence+pos, " \t\n" );
reverse ( sentence + pos, len );
}
reverse ( sentence , pos );
printf("After:%s\n",sentence);
return 0;
}
#include <iostream>
#include <string>
using namespace std;
char* stringrev(char s[], int len)
{
char *s1 = (char*)malloc(len+1);
int i=0;
while (len>0)
{
s1[i++] = s[--len];
}
s1[i++] = '\0';
return s1;
}
void sentrev(char s[], int len)
{
int i=0; int j=0;
char *r = (char*)malloc(len+1);
while(1)
{
if(s[j] == ' ' || s[j] == '\0')
{
r = stringrev(s+i, j-i);
i = j+1;
cout<<r<<" ";
}
if (s[j] == '\0')
break;
j++;
}
}
int main()
{
char *s = "this is a test";
char *r = NULL;
int len = strlen(s);
cout<<len<<endl;
r = stringrev(s, len);
cout<<r<<endl;
sentrev(r, len);
return 0;
}
The above code snap reverse the sentence, using char *r
and printing cout<
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char st[50], rst[50];
printf("Enter the sentence...\n");
gets(st);
int len=strlen(st), p;
int j=-1,k;
p=len;
for(int i=(len-1); i>=0; i--)
{
//searching for space or beginning
if(st[i]==' ')
{
//reversing and storing each word except the first word
for(k=i+1;k<p;k++)
{
//printf("%c",st[k]);
rst[++j]=st[k];
}
j++;
rst[j]=' ';
printf("\n");
p=i;
}
else if(i==0)
{
//for first word
for(k=i;k<p;k++)
{
//printf("%c",st[k]);
rst[++j]=st[k];
}
}
}
printf("Now reversing the sentence...\n");
puts(rst);
return 0;
}
Use a main for loop to traverse till the end of the sentence:
Copy the letters in a string until you find a space.
now call add#beginning function and in that function add the string each time you pass a string to the linked list.
print the contents of the linked list with a space inbetween to get the expected output
My code,just traverse from the last and if you find a space print the characters before it,now change the end to space-1;This will print till the second word,finally just print the first word using a single for loop.Comment for alter approach.
Program:
#include<stdio.h>
int main()
{
char str[200];
int i,j,k;
scanf("%[^\n]s",&str);
for(i=0;str[i]!='\0';i++);
i=i-1;
for(j=i;j>=0;j--)
{
if((str[j])==' ')
{
for(k=j+1;k<=i;k++)
{
printf("%c",str[k]);
}
i=j-1;
printf(" ");
}
}
for(k=0;k<=i;k++)
{
printf("%c",str[k]);
}
}
using stack
#include <iostream>
#include <stdio.h>
#include <stack>
int main()
{
std::stack<string> st;
char *words= "this is a test";
char * temp = (char *)calloc(1, sizeof(*temp));
int size1= strlen(words);
int k2=0;
int k3=0;
for(int i=0;i<=size1;i++)
{
temp[k2] = words[i];
k2++;
if(words[i] == ' ')
{
k3++;
if(k3==1)
temp[k2-1]='\0';
temp[k2]='\0';
st.push(temp);
k2=0;
}
if(words[i] == '\0')
{
temp[k2]='\0';
st.push(temp);
k2=0;
break;
}
}
while (!st.empty())
{
printf("%s",st.top().c_str());
st.pop();
}

Resources