Program gives segmantation fault while using wildcard (*) as first input - c

/*Input string argument can be up to 3 integer numbers,
separated by spaces. A wild card value, represented by a *
character can replace any one of the integer numbers.*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
void parse(char *data);
int program = 0, version = 0, process = 0;
unsigned char flags = 0;
#define GOT_PROG 0x01
#define GOT_VERS 0x02
#define GOT_PROC 0x04
int main()
{
char data[] = " * 10 7 ";
parse(data);
system("PAUSE");
return 0;
}
void parse(char *data)
{
char *tmp = NULL;
/* advance past whitespace */
while(isspace((int)*data)) data++;
if(*data != '*')
{
program = strtoul(data,&tmp,0);
flags|=GOT_PROG;
printf("%d 11\n",program );
}
if(*tmp == '\0') return;
data=++tmp;
if(*data != '*')
{
version = strtoul(data,&tmp,0);
flags|=GOT_VERS;
printf("%d 22\n",version);
}
else
{
tmp++;
}
if(*tmp == '\0') return;
data=++tmp;
if(*data != '*')
{
process = strtoul(data,&tmp,0);
flags|=GOT_PROC;
printf("%d 33\n",process);
}
}
When my inputs are 3 integers it runs fine.
When my Inputs are two ints and one * it runs fine except when I replace 1st integer with an *, not sure where am I going wrong!! Any suggestions?

Logic error in this block:
char *tmp = NULL;
/* advance past whitespace */
while(isspace((int)*data)) data++;
// If *data == '*', you are skipping the code inside the if block.
// tmp continues to be NULL.
if(*data != '*')
{
program = strtoul(data,&tmp,0);
flags|=GOT_PROG;
printf("%d 11\n",program );
}
// Now you are dereferencing a NULL pointer
// and then setting the value of data to 'NULL + 1'.
if(*tmp == '\0') return;
data=++tmp;
I didn't follow the entire logic of your function but you have to add code that deals with the case of *data == '*'.

Inside your parse(), you're doing
char *tmp = NULL;
then, in case of *data equals *, (Remember, the erroneous case input starts with *) without changing tmp, you're doing
if(*tmp == '\0')
i.e., dereferencing invalid pointer, which in turn invokes undefined behaviour.
You need to take care of the access to tmp in case of the input has a leading *.
FWIW, in the same regards, data=++tmp; is also invalid.
Suggestion: After seeing your logic, I suggest to tokenize the input string using strtok(). That is far better option.

Related

C : removing duplicated letters from string

I am trying to remove duplicated letters in each word from string.(I haven't specified it for upper and lower case letters yet)
Input:
Ii feel good todday!!
thhis iss fixed
Output:
I fel god today!
this is fixed
I am calling this function in the main and i have to use the result in another function. That's why I call it by reference.
int main(){
char string[100];
printf("Enter a string:");
gets(string);
dup_letters_rule(&string);
return 0;
}
void dup_letters_rule(char *str_[]){
char new_str_[100];
int i=0, j=0;
printf("Fixed duplicates:\n");
while(*str_[i]!='\0'){
if(*str_[i]== *str_[i+1] && *str_[i+1]!='\0'){
while(*str_[i]==*str_[i+1] && *str_[i+1]!='\0'){
i++;
}
*str_[i]=new_str_[j];
j++;
i++;
}
else{
*str_[i]=new_str_[j];
j++;
i++;
}
}
new_str_[j]='\0';
puts(new_str_);
}
It works like:
void dup_letters_rule(char *str_[]){
char *new_str_=*str_, *temp=*str_;
temp++;
printf("Fixed duplicates:\n");
while(*new_str_!='\0'){
if(*new_str_== *temp && *temp!='\0'){
while(*new_str_==*temp && *temp!='\0'){
new_str_++;
temp++;
}
putchar(*new_str_);
new_str_++;
temp++;
}
else{
putchar(*new_str_);
new_str_++;
temp++;
}
}
}
But then, I can't use *str_ string in another function.
The code can be simplified.
We can keep an int value that is the previous char seen and compare it against the current char and only "copy it out" if they are different. (i.e. we only need two pointers).
We also have to use tolower because Ii goes to I.
Although a second/output buffer could be used, the function can do the cleanup "in-place". Then, the caller can use the cleaned up buffer. This is what we'd normally want to do.
If the caller needs to keep the original string, it can save the original to a temp buffer and call the function with the temp
I had to refactor your code. I tested it against your sample input. It is annotated:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void
dup_letters_rule(char *src)
{
char *dst = src;
int prev = -1;
// rchr -- the "raw" char
// lchr -- the result of tolower(rchr)
// prev -- the previous value of lchr (starts with -1 to force output of
// first char)
for (int rchr = *src++; rchr != 0; rchr = *src++) {
// get lowercase char
int lchr = tolower((unsigned char) rchr);
// output if _not_ a dup
if (lchr != prev)
*dst++ = rchr;
// remember this char for the next iteration
prev = lchr;
}
*dst = 0;
}
int
main(void)
{
char *cp;
char buf[1000];
while (1) {
cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// get rid of newline
buf[strcspn(buf,"\n")] = 0;
// eliminate dups
dup_letters_rule(buf);
// output the clean string
printf("%s\n",buf);
}
return 0;
}
UPDATE:
can i print the clean string in the dup_letters_rule function? – hamster
Sure, of course. We're the programmers, so we can do whatever we want ;-)
There is a maxim for functions: Do one thing well
In many actual (re)use cases, we don't want the simple/low level function to do printing. That is the usual.
But, we could certainly add printing to the function. We'd move the printf from main into the function itself.
To get the best of both worlds, we can use two functions. One that just does the transformation. And, a second that calls the simple function and then prints the result.
Here's a slight change that illustrates that. I renamed my function and created dup_letters_rule with the printf embedded in it:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void
dup_letters_rule_basic(char *src)
{
char *dst = src;
int prev = -1;
// rchr -- the "raw" char
// lchr -- the result of tolower(rchr)
// prev -- the previous value of lchr (starts with -1 to force output of
// first char)
for (int rchr = *src++; rchr != 0; rchr = *src++) {
// get lowercase char
int lchr = tolower((unsigned char) rchr);
// output if _not_ a dup
if (lchr != prev)
*dst++ = rchr;
// remember this char for the next iteration
prev = lchr;
}
*dst = 0;
}
void
dup_letters_rule(char *buf)
{
dup_letters_rule_basic(buf);
// output the clean string
printf("%s\n",buf);
}
int
main(void)
{
char *cp;
char buf[1000];
while (1) {
cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// get rid of newline
buf[strcspn(buf,"\n")] = 0;
dup_letters_rule(buf);
}
return 0;
}
UPDATE #2:
and why it's not char *dst = *src; but char *dst = src; – hamster
This is basic C. We want dst to have the same value/contents that src does. Just as if we did:
int x = 23;
int y = x;
If we do what you're suggesting, the compiler flags the statement:
bad.c: In function ‘dup_letters_rule_basic’:
bad.c:8:14: warning: initialization of ‘char *’ from ‘char’ makes pointer from integer without a cast [-Wint-conversion]
char *dst = *src;
^
Doing char *dst = *src [as you suggest] is using * in two different ways.
Doing char *dst says that dst is defined as a pointer to a char.
Doing *src here [which is the initializer for dst and is an expression], the * is the dereference operator. It says "fetch the value (a char) pointed to by src". Not what we want.
Perhaps this would be more clear if we didn't use an initializer. We use a definition (without an initializer) and set the initial value of dst with an assignment statement:
char *dst; // define a char pointer (has _no_ initial value)
dst = src; // assign the value of dst from the value of src
The assignment [statement] can occur anywhere after the definition and before the for loop/statement. Here's the first few lines of the function body:
char *dst;
int prev = -1;
dst = src;
To remove the duplicate consecutive characters from a string in-place, keep track of position in string where the next character, which is not same as its previous character, to be write and check current processing character with previous character (ignore the difference in their case) except when the character is the first character of string because the first character does not have any character previous to it. If current processing character is same as previous character then move to next character in the string and if they are not same then overwrite the character at tracked position with current processing character and increment tracked position pointer by 1.
Its implementation:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void remove_consecutive_dup_chars (char * pstr) {
if (pstr == NULL) {
printf ("Invalid input..\n");
return;
}
/* Pointer to keep track of position where next character
* to be write in order to remove consecutive duplicate character.
*/
char * p = pstr;
for (unsigned int i = 0; pstr[i] ; ++i) {
if ((i) && (tolower (pstr[i]) == tolower (pstr[i - 1]))) {
continue;
}
*p++ = pstr[i];
}
/* Add the null terminating character.
*/
*p = '\0';
}
int main (void) {
char buf[256] = {'\0'};
strcpy (buf, "Ii feel good todday!!");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "thhis iss fixed");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "aaaaaa zzzzzz");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
return 0;
}
Output:
I fel god today!
this is fixed
a z

Reading Multiple lines until EOF

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//the function
char* scan(char *string)
{
int c; //as getchar() returns `int`
string = malloc(sizeof(char)); //allocating memory
string[0]='\0';
for(int i=0; i<100 && (c=getchar())!='\n' && c != EOF ; i++)
{
string = realloc(string, (i+2)*sizeof(char)); //reallocating memory
string[i] = (char) c; //type casting `int` to `char`
string[i+1] = '\0'; //inserting null character at the end
}
return string;
}
char** bigScan(char **string)
{
int c;
string=malloc(sizeof(char *));
string[0]='\0';
for(int i=0;(c=getchar()!=EOF);i++)
{
*string = realloc(string, (i+2)*sizeof(char *)); //reallocating memory
string[i] = scan(string[i]); //type casting `int` to `char`
string[i+1] = '\0'; //inserting null character at the end
}
return string;
}
int main(void)
{
char **buf; //pointer to hold base address of string
buf=bigScan(buf);
printf("%s\n",buf[0] );
}
So basically the scan function reads each line until either EOF or new line.The job of bigScan is to read multiple lines (pointer to strings) by invoking the scan function until we hit EOF. So essentially the big scan returns pointer to pointers and we can read the entire text using this.
What am I doing wrong in my approach ?
Basically invoking the scan function in my bigScan until I Hit EOF.
Ideal Input:
"Hi guys and girls
This is a message in multiple lines."
Ideal Output:
"Hi guys and girls
This is a message in multiple lines."
The (c=getchar()!=EOF) inside bigScan is invalid. It assigns the value of 1 or 0 to c, as the bool value is the result of != comparison.
The getchar() inside bigScan will make you loose one character per line, as that character is nowhere saved.
The allocation in bigScan is invalid. You shouldn't allocate the memory for string *string = realloc(string, but you should allocate the memory for pointers themselves, ie. string = realloc(string, ... sizeof(char*)).
NULL is the terminating value used for pointers. Don't use '\0' for pointers.
Use size_t to store sizes.
There is little point in passing parameters value if you are overwriting them. In this function the variable a is unused void f(int a) { a = 1; } as the variable string in your both functions are assigned immediately after entering the function.
The function scan has a hard limit of i<100 characters.
Below is somewhat fixed version of your functions. With also renamed variables. And removed parameters. And different indentation. And with assertions from the standard #include <assert.h> to use as a primitive error checking. And with ungetc so the character read in bigScan doesn't disappear. And I haven't run this code, so it has ton of errors.
char* scan(void)
{
char *string = malloc(sizeof(*string));
assert(string != NULL);
string[0] = '\0';
size_t stringlen = 1;
for(int c; (c=getchar()) != '\n' && c != EOF;) {
void * const ptr = realloc(string, (stringlen + 1) * sizeof(*string));
assert(ptr != NULL);
stringlen++;
string[stringlen - 2] = c;
string[stringlen - 1] = '\0'; //inserting null character at the end
}
return string;
}
char** bigScan(void)
{
char **strings = malloc(sizeof(*strings));
assert(strings != NULL);
strings[0] = NULL;
size_t stringslen = 1;
for(int c; (c = getchar()) != EOF;) {
ungetc(c);
void * const ptr = realloc(strings, (stringslen + 1) * sizeof(*strings));
assert(ptr != NULL);
strings = ptr;
stringslen++;
strings[stringslen - 2] = scan();
strings[stringslen - 1] = NULL;
}
return strings;
}

C program strings

For part of my program I would like to concatenate two strings together with an asterisk between each character. For example, if I had a first string of "abcde" and a second string of "1234567", I would like to have a result of "a*b*c*d*e*1*2*3*4*5*6*7*".
For this part of the program I have:
char *widen_stars(char *one, char *two)
{
int length_one = strlength(one); // length of first parameter
int length_two = strlength(two); // Length of second parameter
char *p = malloc((sizeof(char) * (length_one + length_two) * 2)+ 1), *p_start; //Allocate enough memory for both strings concatenated together with a * between each letter
p_start = p;
while(*one != '0')
{
if( (p - p_start) % 2 == 0) // Keeps track of where we are in the p string
{
*p = *one;
p++;
one++;
}
else
{
*p = '*';
p++;
}
}
while(*two != '0')
{
if( (p - p_start) % 2 == 0)
{
*p = *two;
p++;
two++;
}
else
{
*p = '*';
p++;
}
}
return p_start;
}
int main(int argc, char *argv[])
{
char first[31]= {0};
char second[31]= {0};
char *f = first, *s = second;
printf("Please enter a string of maximum 30 characters: ");
scanf("%s", f);
printf("Please enter a string of maximum 30 characters: ");
scanf("%s", s);
printf("The combined string is: %s\n", widen_stars(f, s));
}
return 0;
}
However, when I run the program with the above inputs, I get something like "a*b*c*d*e*", without any of the second string. If I block out the first while loop into comments to test the second loop, I get something like "1*2*3*4*5*5*7*", which leaves me scratching my head.
Your problem lies here:
while(*oneOrTwo != '0')
If you're looking for the end of the strings, it's '\0' that you should be looking for, not '0'. The former is the end-of-string marker, the latter is simply the character 0.
And, as an aside, there are much less ..., err, verbose ways to do this (assuming it's not class work - if it is, you should go with your current method). For example:
#include <stdio.h>
#include <string.h>
char *widen_stars(char *one, char *two) {
// Need to cater for memory exhaustion.
char *p = malloc((strlen(one) + strlen(two)) * 2) + 1);
if (p == NULL) return NULL;
// Init to empty string in case both inputs empty.
*p = '\0';
// Save string start for return.
char *p_start = p;
// Add character and asterisk for every character in both strings.
while (*one != '\0') {
sprintf(p, "%c*", *one++);
p += 2;
}
while (*two != '\0') {
sprintf(p, "%c*", *two++);
p += 2;
}
// Remove last asterisk (if needed).
// *(--p) = '\0';
// Return result.
return p_start;
}
That's based on your actual expected results, which place an asterisk after each character. However, your specifications call for an asterisk between each character. If you decide to got for the latter, it's a simple matter of un-commenting the penultimate statement in the function, to basically back up and replace the final asterisk with an end-of-string marker.
The problem in your code is in while conditions, you should increment pointers until '\0' not '0'. So instead of doing:
while(*one != '0')
...
while(*two != '0')
You do it like this:
while(*one != '\0')
...
while(*two != '\0')
And as you are returning a dynamically allocated memory, consider using a pointer to this memory, which you free after usage:
char *str = widen_stars(f, s);
printf("The combined string is: %s\n", str);
free(str);

Remove specified char from strings in C

I am making a program that will search in an array of strings, and for each string, it will search for a specified char. If it finds that char, remove it. In this example I want to remove the character 'r'.
Here is the code:
void convertStrings(char **line) {
for (int str = 0; str < MAX_LINE_LENGTH; ++str) {
for (int ch = 0; ch < MAX_STR_LENGTH; ++ch) {
if (line[str][ch] == 'r') {
removeChar(line[str], 'r');
}
}
}
}
void removeChar(char *str, char c) {
int i = 0;
int j = 0;
while (str[i]) {
if (str[i] != c) {
str[j++] = str[i];
}
i++;
}
str[j]=0;
}
I am not sure if the algorithm for the removal of chars is correct, however the main mistake is elsewhere. More specifically, I get a segmentation fault in the line:
if (line[str][ch] == 'r') {
Why am I getting a seg fault? Also, is the algorithm for removeChar correct?
Here is my main function:
int main() {
char line[3][10] = {"pep", "rol", "rak"};
printf("%s\n", line[1]);
convertStrings(line);
printf("%s\n", line[1]);
return 0;
}
Thanks in advance.
This code works on my compiler :
#include<stdio.h>
#include<conio.h>
#define MAX_LINE_LENGTH 1024
#define MAX_STR_LENGTH 4
void removeChar(char *str, char c) {
int i = 0;
int j = 0;
while (str[i]) {
if (str[i] != c) {
str[j++] = str[i];
}
i++;
}
str[j]=0;
}
void convertStrings(char line[][MAX_STR_LENGTH]) { //change 1
for (int str = 0; str < MAX_LINE_LENGTH; ++str) {
for (int ch = 0; ch < MAX_STR_LENGTH; ++ch) {
if (line[str][ch] == 'r') {
removeChar(line[str], 'r');
}
}
}
}
int main() {
char line[3][MAX_STR_LENGTH] = {"pep", "rol", "rak"}; //change 2
printf("%s\n", line[1]);
convertStrings(line);
printf("%s\n", line[1]);
getch();
return 0;
}
It's because line[str][ch] doesn't exist for all the value you give to str and/or ch.
You should check the value of MAX_LINE_LENGTH and MAX_STR_LENGTH and be sure that they are right.
The seg fault may be because you are using the constants "MAX_LINE_LENGTH" and "MAX_STR_LENGTH" however there may have the line length or string length. I would use the length of the array for the variable str in the first for loop instead of "MAX_LINE_LENGTH" and the length of array[str] instead of "MAX_STR_LENGTH". Unless each array you are searching has "MAX_LINE_LENGTH" and each string has "MAX_LINE_LENGTH" you will get a set fault. Hope this helps!
EDIT: you can find the length of the array by dividing the size of the array and the size of the type of the element.
sizeof(array)/sizeof(array[0])
finding the size of the char pointer is basically the same process.
You are getting a segfault either because array line contains fewer than MAX_LINE_LENGTH string pointers, or because at least one of the pointed-to strings contains fewer than MAX_STR_LENGTH characters; more likely the latter.
Instead of assuming a fixed number of strings of fixed length, you would be better off passing the actual number of strings as an argument. Alternatively, you could add NULL as sentinel value at the end of the list.
Moreover, there is no reason whatever to assume that each string is a fixed length. Look for the terminating character ('\0') to recognize when you've reached the end. For example:
void convertStrings(char **line) {
for (char **l = line; *l != NULL; l += 1) {
for (int ch = 0; (*l)[ch]; ch += 1) {
if ((*l)[ch] == 'r') {
removeChar(*l, 'r');
}
}
}
}
Your removeChar() function looks ok.
Do note, however, that there are library functions that could help with this (e.g. strchr()), and that there are various efficiency improvements possible (such as passing to removeChar() only the string tail, starting at the first appearance of the character to remove).
You have the array
char line[3][10] = {"pep", "rol", "rak"};
When you pass it to a function, it gets converted into a pointer of type char(*)[10]. So change
void convertStrings(char **line) {
to
void convertStrings(char (*line)[10]) {
or
void convertStrings(char line[][10]) {
An array of arrays (2D array) cannot be converted to a pointer to a pointer(in this case, char**)
Another problem is that you mention that MAX_LINE_LENGTH is 1024 and MAX_STR_LENGTH is 4. This is wrong as the loop would iterate and you access invalid memory locations. You should make MAX_LINE_LENGTH as 3 and MAX_STR_LENGTH as 4 as there are 3 strings, each with 4 characters.
You can also pass these variables as parameters to the function convertStrings. Change add two more parameters in the declartion of convertStrings:
void convertStrings(char (*line)[10], int MAX_LINE_LENGTH, int MAX_STR_LENGTH) {
or
void convertStrings(char line[][10], int MAX_LINE_LENGTH, int MAX_STR_LENGTH) {
and call the function from main using
convertStrings(line, sizeof(line)/sizeof(*line), sizeof(*line)/sizeof(**line)); // `/sizeof(**line)` is 1 and is not needed
A better way would be to use
void convertStrings(int MAX_LINE_LENGTH, int MAX_STR_LENGTH, char line[][MAX_STR_LENGTH]) {
or
void convertStrings(int MAX_LINE_LENGTH, int MAX_STR_LENGTH, char (*line)[MAX_STR_LENGTH]) {
and call the function using
convertStrings(sizeof(line)/sizeof(*line), sizeof(*line)/sizeof(**line), line); // `/sizeof(**line)` is 1 and is not needed
so that you can avoid using the magic number 10 in your function.
You would've certainly got some warnings from your compiler. Pay attention to them. If you did not get warnings, crank up the warnings in your compiler and include warning flags ( like -Wall in GCC ).
BTW, You can look into the strchr function from string.h to find if a character exists in a string.
Why do you check if you encounter the 'r' character twice? (in both function)
checking once would be enough.
A function to detect the char, and a function to delete it?
I would have done it this way :
#include <string.h>
#include <stdio.h>
void convertStrings(char *line);
void removeChar(char *str);
int main(int argc, char *argv[]) {
if (argc == 2)
{
printf("%s\n", argv[1]);
convertStrings(argv[1]);
printf("%s\n", argv[1]);
}
return (0);
}
void convertStrings(char *line)
{
for (int i = 0; line[i] != '\0'; i++)
{
if (line[i] == 'r') removeChar(&(line[i]));
}
}
void removeChar(char *str)
{
int i;
i = 0;
while (str[i] != '\0')
{
str[i] = str[i + 1];
i++;
}
}
But here is another one solution with only one function :
void convertStringsbis(char *line)
{
int delta;
int i;
i = 0;
delta = 0;
while (line[i++ + delta] != '\0')
{
if (line[i + delta] == 'r')
delta++;
line[i] = line[i + delta];
}
}

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