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

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++]);
}

Related

Restrict string size and display the rest of the string in next line

I'm working on a string formatting problem where I'm trying to display the string to the specified size. I need to split the string after 4 commas and display the string in the next line.
INPUT:
char *str = "0-2025,0-2024,0-2023,0-2022,0-2021,0-2020,0-2019,0-2018,0-2017,0-2016";
EXPECTED OUTPUT:
0-2025,0-2024,0-2023,0-2022
0-2021,0-2020,0-2019,0-2018
0-2017,0-2016
I'm trying to add a special character '*' so that I can tokenize and use if for display.
My approach and code is given below, but I'm facing some issue when special character is added at the end.
#include <stdio.h>
#include <string.h>
int nthChar(char *str, char ch, int N){
int occur = 0;
for (int i = 0; i < strlen(str); i++) {
if (str[i] == ch) {
occur += 1;
}
if (occur == N)
return i;
}
}
int main()
{
char *str = "0-2025,0-2024,0-2023,0-2022,0-2021,0-2020,0-2019,0-2018,0-2017,0-2016,0-2015,0-2014,0-2013,0-2012,0-2011,0-2010";
char ch = ',';
int N = 4, res;
res = nthChar(str,ch,N);
printf("%d\n", res);
char priority[128];
strcpy(priority,str);
int size=strlen(str);
printf("size = %d\n",size);
int d = size/res;
printf("DIV =%d\n",d);
printf("%s\n", priority);
for(int i=0;i<strlen(str)&&res<strlen(str);i++){
for(int j=1,k=0;j<=d,k<d;j++,k++){
priority[res*j+k] = '*';
}
}
printf("%s", priority);
return 0;
}
Current Output :
27
size = 111
DIV =4
0-2025,0-2024,0-2023,0-2022,0-2021,0-2020,0-2019,0-2018,0-2017,0-2016,0-2015,0-2014,0-2013,0-2012,0-2011,0-2010
0-2025,0-2024,0-2023,0-2022*0-2021,0-2020,0-2019,0-2018*0-2017,0-2016,0-2015,0-2014*0-2013,0-2012,0-2011,0-2010*�O?��
you can create a function which will split with comma and then slice from 0 index to 4 index. With this you can create a div and append them anywhere. Here is the code:
const comaSplit = () => {
const text = document.getElementById('main').innerText
const array = text.split(',')
let init = 0
for (i = 0; i < array.length; i += 4) {
const first = array.slice(init, (init + 4))
const string = first.join(',')
init = init + 4
const div = document.createElement('div')
div.innerText = string
document.getElementById('root').appendChild(div)
}
}
comaSplit()
#include <stdio.h>
#include <string.h>
int nthChar(char *str, char ch, int N){
int occur = 0;
for (int i = 0; i < strlen(str); i++) {
if (str[i] == ch) {
occur += 1;
}
if (occur == N)
return i;
}
}
int main()
{
char *str = "0-2025,0-2024,0-2023,0-2022,0-2021,0-2020,0-2019,0-2018,0-2017,0-2016,0-2015,0-2014,0-2013,0-2012,0-2011,0-2010";
char ch = ',';
int N = 4, res;
res = nthChar(str,ch,N);
char priority[128];
strcpy(priority,str);
int size=strlen(str);
//printf("size = %d\n",size);
int d = size/res;
//printf("DIV =%d\n",d);
//printf("%s\n", priority);
for(int j=1,k=0;j<=d,k<d && res<strlen(str);j++,k++){
if((res*j+k)==size){
//printf("End of the string check\n");
priority[res*j+k] = '\0';
}else {
//printf("index =%d\n",(res*j+k));
priority[res*j+k] = '*';
}
}
char* token = strtok(priority, "*");
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, "*");
}
return 0;
}
OUTPUT:
0-2025,0-2024,0-2023,0-2022
0-2021,0-2020,0-2019,0-2018
0-2017,0-2016,0-2015,0-2014
0-2013,0-2012,0-2011,0-2010
I've tried an approach to find nth comma and then replace that with a distinct special character to tokenize it later for display purpose.
By reading blogs and more about char array I understood that the last character of the string should be '\0' which is by default handled.
I've tried a approach of changing every 4th comma to a special character and then tokenizing with that to display the output.

If a string is rotation of other. All test cases Not running

I am using the logic of concatenation the 2nd string and then searching first string in it.
But for some reason, the code does not run for all test cases.
example
s1 = rahul , s2 = hulra
s2.s2 = hulrahulra
and then search s1 in s2.s2 using strstr() function.
#include <stdio.h>
#include <string.h>
int ifRotation(char *s1, char *s2)
{
int l1 = strlen(s1);
int l2 = strlen(s2);
char str1[l1], str2[l2+ l2];
int i;
i = 0;
while(*s1 != '\0')
{
str1[i] = *s1;
i++;
s1++;
}
i = 0;
while(*s2 != '\0')
{
str2[i] = *s2;
i++;
s2++;
}
strcat(s2, s2);
if(strstr(s2, s1))
{
return 1;
}
return 0;
}
int main() {
//code
int queries;
scanf("%d", &queries);
int array[queries];
char str1[100];
char str2[100];
int i = 0;
while(i < queries)
{
scanf("%s", &str1);
scanf("%s", &str2);
array[i] = ifRotation(str1, str2);
i++;
}
i = 0;
while(i < queries)
{
printf("%d\n", array[i]);
i++;
}
return 0;
}
Please tell me what's wrong with the code?
You are just copying from one string to another, and the copy routine has several problems.
char str1[l1] is not large enough. It should be char str1[l1 + 1]. The extra 1 is for the null character.
The string should always end with null character '\0'.
s1 and s2 are incremented until they reach the null character, so by that time s1 and s2 are empty.
Try the following code for copying the strings, you will see s1/s2 will be empty, str1/str2 are just copies of the original s1/s2.
You can fix the copying as follows:
char str1[l1 + 1], str2[l2 + 1];
int i;
i = 0;
while(*s1 != '\0')
{
str1[i] = *s1;
i++;
s1++;
}
str1[i] = '\0';
i = 0;
while(*s2 != '\0')
{
str2[i] = *s2;
i++;
s2++;
}
str2[i] = '\0';
printf("s1=%s, s2=%s, str1=%s, str2=%s\n", s1, s2, str1, str2);
//output: s1=, s2=, str1=old_s1, str2=old_s2
But this doesn't really achieve anything. If you just want to check "rahul" is the reverse of "hulra", keep s1 as it is, copy s2 to reverse_s2 in reverse order, and compare the two strings as follows:
#include <stdio.h>
#include <string.h>
int ifRotation(const char *s1, const char *s2)
{
if(!s1 || !s2)
return 0;
int len2 = strlen(s2);
char reverse_s2[len2 + 1];
//copy s2 to reverse_s2 in reverse order:
int i = 0;
for(i = 0; i < len2; i++)
reverse_s2[i] = s2[len2 - i - 1];
reverse_s2[i] = '\0'; //add null character
int result = strcmp(s1, reverse_s2) == 0;
return result;
}
int main(void)
{
printf("%d\n", ifRotation("rahul", "hulra"));
printf("%d\n", ifRotation("rahul", "luhar"));
return 0;
}

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

When the string is number C language

I want to return nothing when the string is number
here is my code,
#include <string.h>
#include <ctype.h>
int num = 0;
char* findWord(char* subString) {
char* word = malloc(sizeof(char) * (strlen(subString) + 1));
int i = 0;
int Position = 0;
num = 0;
while (ispunct(subString[i]) != 0 || isspace(subString[i]) != 0) {
i++;
}
num = i;
while (ispunct(subString[i]) == 0 && isspace(subString[i]) == 0) {
word[Position] = subString[i];
i++;
Position++;
}
word[Position] = '\0';
return word;
}
char** wordList(const char* s) {
int len = strlen(s);
int i = 0;
char* Copyword = malloc(sizeof(char) * len);
strncpy(Copyword, s, len);
char** result = (char**) malloc(sizeof(char*) * (len + 1));
char* word = NULL;
word = findWord(Copyword);
char* wordEnd = Copyword;
while (*word != 0) {
result[i] = word;
wordEnd = wordEnd + strlen(word) + num;
word = findWord(wordEnd);
i++;
}
result[i] = '\0';
free(Copyword);
return result;
}
int main(void) {
char** words = wordList("1 23 456 789");
int i = 0;
while (words[i] != NULL) {
printf("%s\n", words[i]);
free(words[i]); // We're done with that word
i++;
}
free(words); // We're done with the list
return 0;
}
my code is ok when the string is sentence.
however, in this case, I want to print nothing(just like a space) when the string is number.
but what I go is
1
23
456
789
I expect to get
nothing shows here! just a space
For starters: You pass a non 0-terminated C-"string" (Copyword) to findWord() and in there call strlen() on it. This just doesn't crash your app by bad luck.

Splitting a string (Segmentation Fault on test)

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

Resources