How to assign char * to character array? - c

I have following code:
int main(){
char sentence[] = "my name is john";
int i=0;
char ch[50];
for (char* word = strtok(sentence," "); word != NULL; word = strtok(NULL, " "))
{
// put word into array
// *ch=word;
ch[i]=word;
printf("%s \n",ch[i]);
i++;
//Above commeted part does not work, how to put word into character array ch
}
return 0;
}
I am getting error: error: invalid conversion from ‘char*’ to ‘char’ [-fpermissive]
I want to store each word into array, can someone help?

To store a whole set of words you need an array of words, or at least an array of pointers pointing to a word each.
The OP's ch is an array of characters and not an array of pointers to characters.
A possible approach would be:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define WORDS_MAX (50)
int main(void)
{
int result = EXIT_SUCCESS;
char sentence[] = "my name is john";
char * ch[WORDS_MAX] = {0}; /* This stores references to 50 words. */
char * word = strtok(sentence, " "); /* Using the while construct,
keeps the program from running
into undefined behaviour (most
probably crashing) in case the
first call to strtok() would
return NULL. */
size_t i = 0;
while ((NULL != word) && (WORDS_MAX > i))
{
ch[i] = strdup(word); /* Creates a copy of the word found and stores
it's address in ch[i]. This copy should
be free()ed if not used any more. */
if (NULL == ch[i])
{
perror("strdup() failed");
result = EXIT_FAILURE;
break;
}
printf("%s\n", ch[i]);
i++;
word = strtok(NULL, " ")
}
return result;
}

Related

How to split a string into separate words and create the array of these words in C language?

So, the task is the following:
Find the number of words in the text in which the first and last characters are the same.
In order to do this, I think I first should split the text and create the array of separate words.
For example, the string is:
"hello goodbye river dog level"
I want to split it and get the following array:
{"hello", "goodbye", "river", "dog", "level"}
I have the code that splits the string:
#include<stdio.h>
#include <string.h>
int main() {
char string[100] = "hello goodbye river dog level";
// Extract the first token
char * token = strtok(string, " ");
// loop through the string to extract all other tokens
while( token != NULL ) {
printf( " %s\n", token ); //printing each token
token = strtok(NULL, " ");
}
return 0;
}
However, it just prints these words, and I need to append each word to some array. The array shouldn't be of fixed size, because potentially I could add as many elements as the text requires. How to do this?
I don't see any reason to split into words. Just iterate the string while keeping a flag that tells whether you are inside or outside a word (i.e. a state variable). Then have variables for first and last character that you maintain as you iterate. Compare them when you go out of a word or reach end-of-string.
A simple approach could look like:
#include <stdio.h>
int count(const char* s)
{
int res = 0;
int in_word = 0;
char first;
char last;
while(*s)
{
if (in_word)
{
if (*s == ' ')
{
// Found end of a word
if (first == last) ++res;
in_word = 0;
}
else
{
// Word continues so update last
last = *s;
}
}
else
{
if (*s != ' ')
{
// Found start of new word. Update first and last
first = *s;
last = *s;
in_word = 1;
}
}
++s;
}
if (in_word && first == last) ++res;
return res;
}
int main(void)
{
char string[100] = "hello goodbye river dog level";
printf("found %d words\n", count(string));
return 0;
}
Output:
found 2 words
Note: Current code assumes that word delimiter is always a space. Further the code doesn't treat stuff like , . etc. But all that can be added pretty easy.
Here is a simple (but naive) implementation based on the existing strtok code. It doesn't just count but also points out which words that were found, by storing a pointer to them in a separate array of pointers.
This works since strtok changes the string in-place, replacing spaces with null terminators.
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[100] = "hello goodbye river dog level";
char* words[10]; // this is just assuming there's not more than 10 words
size_t count=0;
for(char* token=strtok(string," "); token!=NULL; token=strtok(NULL, " "))
{
if( token[0] == token[strlen(token)-1] ) // strlen(token)-1 gives index of last character
{
words[count] = token;
count++;
}
}
printf("Found: %zu words. They are:\n", count);
for(size_t i=0; i<count; i++)
{
puts(words[i]);
}
return 0;
}
Output:
Found: 2 words. They are:
river
level
with strtok based on Alexander's code.
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[] = "hello, goodbye; river, dog; level.";
char *token = strtok(string, " ,;.");
int counter =0;
while( token != NULL )
{
if(token[0]==token[strlen(token)-1]) counter++;
token = strtok(NULL, " ,;.");
}
printf("found : %d", counter);
return 0;
}

C Program - Error Combine String Array into Program

I'm trying to write program to ask user to enter First and Last Name. Then my program will result their Full Name (combined First + Last Name) and the length of their Full Name. My Output right now does empty Full Name and 0 length. I guess my problem is at display_name functions. Here is my code so far. Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void display_name(char *fullname);
int count_char( char*x_ptr);
char * get_name(char * first_name, char * last_name);
#define MAX 80 // maximum number of array elements
int main(void)
{
char first_name[MAX];
char last_name[MAX];
char *x_ptr;
system("cls");
printf("Enter Last Name: \n" );
scanf("%s", &last_name );
printf("Enter First Name: \n" );
scanf("%s", &first_name );
x_ptr = get_name(first_name, last_name);
display_name(x_ptr);
puts("");
system("pause");
return 0;
}
char * get_name(char *first_name, char *last_name)
{
static char fullname[MAX];
char x;
x = 0;
strcpy(fullname, first_name);
strcat(fullname, " ");
strcat(fullname, last_name);
while (((fullname[x] = getchar()) != '\n') && (x < (MAX-1)))
{
x++;
}
fullname[x] = '\0';
return(fullname);
}
/* Function to print out string passed to it and display the length of fullname*/
void display_name(char *fullname)
{
char *a;
printf("Your Full name is ");
a = &fullname[0];
while (*a != '\0')
{
putchar(*a);
a++;
}
int length;
length = strlen(fullname);
printf("\nHas %d Characters", length);
length = count_char(fullname);
printf("\nHas %d Non Space Characters", length);
}
/* function to return count of non space characters*/
int count_char( char * x_ptr)
{
char *b;
unsigned int count=0;
b = x_ptr;
while (*b != '\0')
{
if (*b != ' ')
count++;
b++;
}
return
(count);
}
scanf("%s", &last_name );
Compiler complained and you ignored it. It should be scanf("%s", last_name );. Same goes with firstname. Yours had type char (*)[] and scanf expects char* which is what we gave in second case.
This part is doing nothing that you would do to achieve what you are trying to do.
while (((fullname[x] = getchar()) != '\n') && (x < (MAX-1)))
This is using getchar to get the characters from stdin and put it in the char array where you are storing the concatenated name.
Using static char array is not a good solution. The next time you try to use this function - it will overwrite the data previously written by another function. Illustration implementation of the function get_name would be
char * get_name(char *first_name, char *last_name)
{
char *fullname = malloc(strlen(first_name)+2+strlen(last_name));
if(!fullname){
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(fullname, first_name);
strcat(fullname, " ");
strcat(fullname, last_name);
return fullname;
}
Benefit of using this implementation is that - now the data that is being used is not closely coupled with the methods that call this one. So it can be reused independent of it's previous usage in another function.
Also when using the function get_name remember to free the dynamically allocated memory when you are done working with it.

How to pass a character string to a function in C

I am trying to process a character string in order to change something in a file. I read from a file a character string which contains a command and an argument, separated by a space character. I separated this array in tokens.
Now I want to pass the second token, which is the argument to a function. My problem is that when I run my program, the screen freezes and nothing happens. Here is my separating way and the call to the function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void create_file(char *argument)
{
//some code goes here
}
int main()
{
int i = -1;
char *token[5];
char command[20];
const char delim[1] = " ";
FILE *fin;
fin = fopen("mbr.op", "r");
while(fscanf(fin, "%[^\n]", command) == 1)
{
i = -1;
token[++i] = strtok(command, delim);
while(token[i] != NULL)
token[++i] = strtok(NULL, delim);
if(strcmp(token[0], "CREATE_FILE") == 0)
create_file(token[1]);
}
fclose(fin);
return 0;
}
You have a few errors, first command[20] is an uninitialised string and that will cause undefined behaviour. Second, you failed to check the first arg as well as the second, so I added a test where commented. Also, the strings are not long enough so I removed the length. Lastly I test for a NULL pointer passed to the function.
Edit code was added to the question to show that command[20] was initialised, but it is still too short to take the command and a reasonable file name (thanks to #ameyCU).
#include <stdio.h>
#include <string.h>
void create_file(char *argument)
{
if(argument == NULL)
printf("NULL pointer\n");
else
printf("Arg: %s\n", argument);
}
int main(void)
{
int i = -1;
char *token[5];
char command[] = "CREATE_FILE myfile.txt";
const char delim[] = " ";
token[++i] = strtok(command, delim);
while(token[i] != NULL)
token[++i] = strtok(NULL, delim);
if(token[0] != NULL && strcmp(token[0], "CREATE_FILE") == 0) // added test
create_file(token[1]);
return 0;
}
Program output
Arg: myfile.txt
The first error is present in array definition:
const char delim[1] = " ";
In C "" is a string - an array of characters delimited by '\0'. This means that what stands to the right of "=" is a string of two chars:
// ' ' + '\0'
//0x20 0x00
Therefore this should be an array of two chars:
const char delim[2] = " ";
or
const char delim[] = " ";

How do I split elements in an array of unsigned char

I have the following:
unsigned char input[];
unsigned char *text = &input[];
I'm taking in user input as follows:
do {
printf ("Please enter an numeric message terminated by -1:\n");
fgets(input, sizeof(input), stdin);
}
while (input[0] == '\n')
Since my output will give me an array of individual characters, how
can I go about concatenating them. If I enter input such as:
14 156 23 72 122
when I try to work with it, it's breaking it into:
1 4 1 5 6 ...
In other words, when I want to pass it to a function as an unsigned char,
I want to pass '14', so the function can read the binary of 14, rather than
1, then 4, etc. Any help would be greatly appreciated!
As it stands now, your code does not compile.
You cannot declare these variables like this:
unsigned char input[];
unsigned char *text = &input[];
You need to say how big input is supposed to be. I'm not sure what you're doing with your second definition.
You also need to put a semicolon after this line
while (input[0] == '\n')
All of that aside, if the input is separated by a know delimiter, you could use strtok() instead of reading the string byte by byte.
I scrapped your program because it didn't compile. This is what I assume you're trying to do with your code, adjust accordingly:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
* Converts "input" separated by "delims" to an array of "numbers"
*/
size_t str_to_nums(const char* input, const char* delims, int* numbers, size_t numsize)
{
char* parsed = malloc(strlen(input) + 1); /* allocate memory for a string to tokenize */
char* tok; /* the current token */
size_t curr; /* the current index in the numbers array */
strcpy(parsed, input); /* copy the string so we don't modify the original */
curr = 0;
tok = strtok(parsed, delims);
while(tok != NULL && curr < numsize) { /* tokenize until NULL or we exceed the buffer size */
numbers[curr++] = atoi(tok); /* convert token to integer */
tok = strtok(NULL, delims); /* get the next token */
}
free(parsed);
return curr; /* return the number of tokens parsed */
}
int main(void)
{
char input[256];
int numbers[64];
size_t count, i;
puts("Please enter an numeric message terminated by -1:");
fgets(input, sizeof(input), stdin);
count = str_to_nums(input, " ", numbers, sizeof(numbers)/sizeof(*numbers)); /* string is separated by space */
for(i = 0; i < count; ++i) {
printf("%d\n", numbers[i]); /* show the results */
}
}
P.s. This is not concatenation. The phrase your looking for is "string splitting" or "tokenizing".
Try this!
#include <string.h>
#include <stdio.h>
int main()
{
char *line;
char *token;
scanf(" %[^\n]s",line);
/* get the first token */
token = strtok(line, " ");
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
token = strtok(NULL, " ");
}
return(0);
}

What is the best way to read a string as a command with a whitespace separated argument?

I'm currently writing a primitive shell that lets user input few basic commands: ls, cat etc. I'm taking from the user an input like: ls /home/someUser/someDirectory and storing this in a character array, say input. I've written a few little such functions ls, cat etc. that take an argument and print to stdout the expected result.
What I'd like to know is: what would be the best way to break this input up into a command and argument? For the said example, I'd like to get two different chunks: ls and /home/someUser/someDirectory, so that I can check what command the user wants to execute with what argument. Sure, I can maintain pointers and check the first few characters of the array and compare them and then proceed to the character after whitespace and parse the argument accordingly, but that would be very tedious and inefficient. Is there a better way to do this, possibly an in-built function?
Thanks in advance.
Check this out
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **split(char *const source, const char *const delimiter)
{
size_t length;
char **list;
size_t count;
char *pointer;
char *token;
void *saved;
if ((source == NULL) || (delimiter == NULL))
return NULL;
list = NULL;
pointer = source;
count = 0;
while ((token = strtok(pointer, delimiter)) != NULL)
{
saved = realloc(list, (1 + count) * sizeof(*list));
if (saved == NULL)
goto abort;
length = strlen(token);
list = saved;
list[count] = malloc(1 + length);
if (list[count] == NULL)
goto abort;
strcpy(list[count], token);
pointer = NULL;
count++;
}
saved = realloc(list, (1 + count) * sizeof(*list));
if (saved == NULL)
return list;
list = saved;
list[count] = NULL;
return list;
abort:
while (count != 0)
free(list[count--]);
free(list);
return NULL;
}
int main()
{
size_t k;
char string[] = "example string with spaces";
char **list;
list = split(string, " ");
if (list == NULL)
return -1;
k = 0;
while (list[k] != NULL)
{
printf("%s\n", list[k]);
free(list[k]);
k++;
}
free(list);
return 0;
}
The split function will return an array of char pointers which contain the tokens, and have a sentinel NULL pointer that tells you where the end of the list is.
You could try using strtok:
#include <string.h>
#include <stdio.h>
int main(){
char example_input[80] = "ls /home/user/directory/file.ext";
const char s[2] = "-";
char *token = strtok(example_input, " ");
/* walk through other tokens */
while( token != NULL ){
printf("%s\n", token );
token = strtok(NULL, s);
}
return(0);
}
Escape characters will be somewhat trickier.
If you only need to divide the string into command and argument this may work:
#include <string.h>
#include <stdio.h>
void cmd_ls(const char *arg){
printf("lsing %s\n",arg);
}
void cmd_pwd(const char *arg){
printf("pwding %s\n",arg);
}
int main(){
char example_input[80] = "psdwd /home/user/directory/file.ext";
const char s[2] = "-";
//Find command, assuming it ends at the first space
//Points to first space in string, will eventually point to beginning of
//command
char *command = strchr(example_input, ' ');
//Will point to beginning of argument
char *argument = NULL;
//If command is not NULL, then there is at least one space, so the string has
//the form "<COMMAND> X" where X is either '\0' (string terminator) or another
//character. If the string contains a space, edit it so that there is a
//terminator after the command. If there is an argument, return a pointer to
//its beginning (which may be a space).
if(command!=NULL){
*(command) = '\0'; //Terminate command string
if(*(command+1)!='\0') //If there are argument characters, point to them
argument = command+1;
}
command = example_input; //Point command to beginning of command
//Do I recognise this command?
if(strcmp(command,"ls")==0){
cmd_ls(argument);
} else if(strcmp(command,"pwd")==0) {
cmd_pwd(argument);
} else {
printf("Unrecognised command!\n");
}
return(0);
}
you can do it simply using scanf. you have to read the input until you get a '\n' character.
the code to do it will be :
scanf("%[^\n]", string);
the total string will be stored in the array string. you can do further string processing to extract the required data.

Resources