I want to delete last character in string
first, i use strtok function
My Input is : "Hello World Yaho"
I use " " as my delimeter
My expectation is this
Hell
Worl
Yah
But the actual output is this
Hello
Worl
Yaho
How can I solve this problem? I can't understand this output
this is my code
int main(int argc, char*argv[])
{
char *string;
char *ptr;
string = (char*)malloc(100);
puts("Input a String");
fgets(string,100,stdin);
printf("Before calling a function: %s]n", string);
ptr = strtok(string," ");
printf("%s\n", ptr);
while(ptr=strtok(NULL, " "))
{
ptr[strlen(ptr)-1]=0;
printf("%s\n", ptr);
}
return 0;
}
This program deletes the last character of every word.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char*argv[]){
char *string;
char *ptr;
string = (char*)malloc(100);
puts("Input a String");
fgets(string,100,stdin);
printf("Before calling a function: %s\n", string);
string[strlen(string)-1]=0;
ptr = strtok(string," ");
printf("%s\n", ptr);
while(ptr){
ptr[strlen(ptr)-1]=0;
printf("%s\n", ptr);
ptr = strtok(0, " ");
}
return 0;
}
You must remember to
Trim the string from trailing newline
Use strtok properly
Test
Input a String
Hello World Yaho
Before calling a function: Hello World Yaho
Hello
Hell
Worl
Yah
Your problem is best solved by splitting it in 2 phases: parsing the phrase into words on one hand, with strtok if you wish, and printing the words with their last character omitted in a separate function:
#include <stdio.h>
#include <string.h>
static void print_truncated_word(const char *ptr) {
int len = strlen(ptr);
if (len > 0) len -= 1;
printf("%.*s", len, ptr);
}
int main(int argc, char*argv[]) {
char buf[128];
char *ptr;
puts("Input a string: ");
if (fgets(buf, sizeof buf, stdin) == NULL) {
/* premature end of file */
exit(1);
}
printf("Before calling a function: %s\n", string);
ptr = strtok(string, " \n");
while (ptr) {
print_truncated_word(ptr);
ptr = strtok(NULL, " \n");
}
return 0;
}
Note that the print_truncated_word function does not modify the buffer. Side effects on input arguments should be avoided, unless they are the explicit goal of the function. strtok is ill behaved to this regard, among other shortcomings such as its hidden state that prevents nested use.
Since you kept the delm as space it will create separate tokens for space separated words in your string and c-style strings contain their last characters as '\0' i.e null character so it deletes that character and not your last character in the text.
check this out
http://www.cprogramming.com/tutorial/c/lesson9.html
it turns out that C-style strings are always terminated with a null character, literally a '\0' character (with the value of 0),
Related
I'm trying to write a string spliter function in C.It uses space as delimiter to split a given string in two or more. It more like the split funtion in Python.Here is the code:-
#include <stdio.h>
#include <string.h>
void slice_input (char *t,char **out)
{
char *x,temp[10];
int i,j;
x = t;
j=0;
i=0;
for (;*x!='\0';x++){
if (*x!=' '){
temp[i] = *x;
i++;
}else if(*x==' '){
out[j] = temp;
j++;i=0;
}
}
}
int main()
{
char *out[2];
char inp[] = "HEllo World ";
slice_input(inp,out);
printf("%s\n%s",out[0],out[1]);
//printf("%d",strlen(out[1]));
return 0;
}
Expeted Output:-
HEllo
World
but it is showing :-
World
World
Can you help please?
out[j] = temp;
where temp is a local variable. It will go out of scope as soon as your function terminates, thus out[j] will point to garbage, invoking Undefined Behavior when being accessed.
A simple fix would be to use a 2D array for out, and use strcpy() to copy the temp string to out[j], like this:
#include <stdio.h>
#include <string.h>
void slice_input(char *t, char out[2][10]) {
char *x, temp[10];
int i,j;
x = t;
j=0;
i=0;
for (;*x!='\0';x++) {
if (*x!=' ') {
temp[i] = *x;
i++;
} else if(*x==' ') {
strcpy(out[j], temp);
j++;
i=0;
}
}
}
int main()
{
char out[2][10];
char inp[] = "HEllo World ";
slice_input(inp,out);
printf("%s\n%s",out[0],out[1]);
return 0;
}
Output:
HEllo
World
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
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;
}
You can use this function to split string into tokens - there is no need to use some own functions. Your code looks like garbage, please format it.
Your source propably would look like this:
char *
strtok(s, delim)
char *s; /* string to search for tokens */
const char *delim; /* delimiting characters */
{
static char *lasts;
register int ch;
if (s == 0)
s = lasts;
do {
if ((ch = *s++) == '\0')
return 0;
} while (strchr(delim, ch));
--s;
lasts = s + strcspn(s, delim);
if (*lasts != 0)
*lasts++ = 0;
return s;
}
I'm not good at using C language. Here is my dumb question. Now I am trying to get input from users, which may have spaces. And what I need to do is to split this sentence using space as delimiter and then put each fragment into char* array. Ex:
Assuming I have char* result[10];, and the input is: Good morning John. The output should be result[0]="Good"; result[1]="morning"; result[2]="John";I have already tried scanf("%[^\n]",input); and gets(input); Yet it is still hard to deal with String in C. And also I have tried strtok, but it seems that it only replaced the space by NULL. Hence the result will be GoodNULLmorningNULLJohn. Obviously it's not what I want. Please help my dumb question. Thanks.
Edit:
This is what I don't understand when using strtok. Here is a test code.
The substr still displayed Hello there. It seems subtok only replace a null at the space position. Thus, I can't use the substr in an if statement.
int main()
{
int i=0;
char* substr;
char str[] = "Hello there";
substr = strtok(str," ");
if(substr=="Hello"){
printf("YES!!!!!!!!!!");
}
printf("%s\n",substr);
for(i=0;i<11;i++){
printf("%c", substr[i]);
}
printf("\n");
system("pause");
return 0;
}
Never use gets, is deprecated in C99 and removed from C11.
IMO, scanf is not a good function to use when you don't know the number of elements before-hand, I suggest fgets:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[128];
char *ptr;
fgets(str, sizeof str, stdin);
/* Remove trailing newline */
ptr = strchr(str, '\n');
if (ptr != NULL) {
*ptr = '\0';
}
/* Tokens */
ptr = strtok(str, " ");
while (ptr != NULL) {
printf("%s\n", ptr);
ptr = strtok(NULL, " ");
}
return 0;
}
gets is not recommended to use, as there is no way to tell the size of the buffer. fgets is ok here because it will stop reading when the 1st new line is encountered. You could use strtok to store all the splited words in to an array of strings, for example:
#include <stdio.h>
#include <string.h>
int main(void) {
char s[256];
char *result[10];
fgets(s, sizeof(s), stdin);
char *p = strtok(s, " \n");
int cnt = 0;
while (cnt < (sizeof result / sizeof result[0]) && p) {
result[cnt++] = p;
p = strtok(NULL, " \n");
}
for (int i = 0; i < cnt; i++)
printf("%s\n", result[i]);
return 0;
}
As most of the other answers haven't covered another thing you were asking:
strtok will not allocate temporary memory and will use your given string to replace every separator with a zero termination. This is why Good morning John becomes GoodNULLmorningNULLJohn. If it wouldn't do this, each token would print the whole rest of the string on its tail like:
result[0] = Good morning John
result[1] = morning John
result[2] = John
So if you want to keep your original input and an array of char* per word, you need 2 buffers. There is no other way around that. You also need the token buffer to stay in scope as long as you use the result array of char* pointers, else that one points to invalid memory and will cause undefined behavior.
So this would be a possible solution:
int main()
{
const unsigned int resultLength = 10;
char* result[resultLength];
memset(result, 0, sizeof result); // we should also zero the result array to avoid access violations later on
// Read the input from the console
char input[256];
fgets(input, sizeof input, stdin);
// Get rid of the newline char
input[strlen(input) - 1] = 0;
// Copy the input string to another buffer for your tokens to work as expected
char tokenBuffer[256];
strcpy(tokenBuffer, input);
// Setting of the pointers per word
char* token = strtok(tokenBuffer, " ");
for (unsigned int i = 0; token != NULL && i < resultLength; i++)
{
result[i] = token;
token = strtok(NULL, " ");
}
// Print the result
for (unsigned int i = 0; i < resultLength; i++)
{
printf("result[%d] = %s\n", i, result[i] != NULL ? result[i] : "NULL");
}
printf("The input is: %s\n", input);
return 0;
}
It prints:
result[0] = Good
result[1] = morning
result[2] = John
result[3] = NULL
result[4] = NULL
result[5] = NULL
result[6] = NULL
result[7] = NULL
result[8] = NULL
result[9] = NULL
The input is: Good morning John
Im having a lot of trouble printing up to the string and then replacing the word and then printing the rest of the string. I want to replace the "word" variable with \e[7m word \e[0m. I tried using strcasestr to get to to where word is in the string, and it returns a pointer starting at the string. My question is how do I use this pointer to print the string up to that point, replace the word with \e[7m word \e[0m, then print the rest of the string
struct node *ptr;
int count = 0;
char* filecheck = "";
char* tester = "";
char* pch = "";
char str[1024];
int i;
int j;
int charcount = 0;
int counter = 1;
FILE *fp = fopen(ptr->fileName, "r");
char line [ 1024 ]; /* or other suitable maximum line size */
int counter = 1;
while ( fgets ( line, sizeof line, fp ) != NULL ) /* read a line */{
//print the line
printf("\e[7m %s \e[0m", word);
printf("%s", line);
}
This is a simple way to do it
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char *tester = "Hello my name is Rocky the polar bear";
char *pch = NULL;
char *word = "the";
pch = strcasestr(tester, word);
if (pch != NULL)
{
size_t length;
/* this will give the difference between the pointers */
length = pch - tester;
/* write to stdout from the start of the string just 'length' bytes */
fwrite(tester, 1, length, stdout);
/* write the word you want to substitute */
printf("\033[7m%s\033[0m", word);
/* pch is pointing to the start of 'word' in the string, advance to it's end */
pch += strlen(word);
/* print the rest of the string */
printf("%s", pch);
}
return 0;
}
Printing the part after word is easy: just start at the character strlen(word) characters after where word starts. Printing the replacement is trivial (unless you need to compute the replacement, which you've said nothing about how to do).
That leaves the part before word. If tester didn't have a string constant in it, you could set *pch to 0, terminating the string at the start of word, and just print tester (then put the character you erased back). Instead, you could copy the part of tester to be printed into a character array, and print that.
I have a char array:
char tmp[2048];
I want to cut of the first x words of tmp. I define a word as a sequence of characters that does not include whitespaces. I tried something like this (should cut of the first 3 words):
sscanf(tmp, "%*s %*s %*s %s", tmp);
My problem is, that '%s' stops at the first whitespace it finds. I want the new string to end at the end of the old string, not at the first whitespace.
I'm also open for other suggestions how to cut of the first x words of a string. I define a word as a sequence of characters that doesn't contain whitespaces.
Here's a rough implementation:
const char* TrimWords(const char* input, int nWords)
{
while (nWords)
{
if (!isspace(*input) && isspace(*(input + 1)))
{
nWords--;
}
input++;
}
return input;
}
TrimWords("One Two Three Four Five", 3);
// returns " Four Five" after the first 3 words are trimmed.
Detailed input validation and error checking is left to the OP.
This is just a good starting point.
use strncpy(tmp, n, tmp+m); where m and n are ints
char tmp[20] = "abcdef";
strncpy(tmp, tmp + 3, 2);
for exmaple: code above will result in decdef
You can use strtok to tokenize strings by whitespace. Something similar to this could do what you're trying to achieve:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
// Number of words to trim
const int numWords = 2;
char tmp[1024];
char buffer[1024];
sprintf(tmp, "this is a\tsentence.");
strcpy(buffer, tmp);
char* token = strtok(buffer, " \t");
for (int i = 0; i < numWords && token; i++) {
token = strtok(NULL, " \t");
}
if (token) {
size_t len = 1024 - (token - buffer);
memmove(tmp, tmp + (token - buffer), len);
}
else {
memset(tmp, '\0', 1024);
}
// Prints "a sentence."
printf("%s", tmp);
return 0;
}
However, the use of strtok is tricky at best. I would suggest using an approach similar to that of abelenky's answer.
I have this code which will remove the first occurrence of the word from the sentence:
#include "stdio.h"
#include "string.h"
int delete(char *source, char *word);
void main(void) {
char sentence[500];
char word[30];
printf("Please enter a sentence. Max 499 chars. \n");
fgets(sentence, 500, stdin);
printf("Please enter a word to be deleted from sentence. Max 29 chars. \n");
scanf("%s", word);
delete(sentence, word);
printf("%s", sentence);
}
int delete(char *source, char *word) {
char *p;
char temp[500], temp2[500];
if(!(p = strstr(source, word))) {
printf("Word was not found in the sentence.\n");
return 0;
}
strcpy(temp, source);
temp[p - source] = '\0';
strcpy(temp2, p + strlen(word));
strcat(temp, temp2);
strcpy(source, temp);
return 1;
}
How would I modify it to delete all occurrences of the word in the given sentence? Can i still use the strstr function in this case?
Thanks for the help!
Open to completely different ways of doing this too.
P.S. This might sound like a homework question, but it's actually a past midterm question which I'd like to resolve to prepare for my midterm!
As a side question, if I use fgets(word, 30, stdin) instead of scanf("%s", word), it no longer works and tells me that the word was not found in the sentence. Why?
Try the following
#include <stdio.h>
#include <string.h>
size_t delete( char *source, const char *word )
{
size_t n = strlen( word );
size_t count = 0;
if ( n != 0 )
{
char *p = source;
while ( ( p = strstr( p, word ) ) != NULL )
{
char *t = p;
char *s = p + n;
while ( ( *t++ = *s++ ) );
++count;
}
}
return count;
}
int main( void )
{
char s[] = "abxabyababz";
printf( "%zu\n", delete( s, "ab" ) );
puts( s );
return 0;
}
The output is
4
xyz
As for the question about fgets then it includes the new line character in the string. You have to remove it from the string.
How would I modify it to delete all occurrences of the word in the given sentence?
There are many ways, as you have suggested, and since you are Open to completely different ways of doing this too...
Here is a different idea:
A sentence uses white space to separate words. You can use that to help solve the problem. Consider implementing these steps using fgets(), strtok() and strcat() to break apart the string, and reassemble it without the string to remove.
0) create line buffer sufficient length to read lines from file
(or pass in line buffer as an argument)
1) use while(fgets(...) to get new line from file
2) create char *buf={0};
3) create char *new_str; (calloc() memory to new_str >= length of line buffer)
4) loop on buf = strtok();, using " \t\n" as the delimiter
Inside loop:
a. if (strcmp(buf, str_to_remove) != 0) //approve next token for concatenation
{ strcat(new_str, buf); strcat(new_str, " ");}//if not str_to_remove,
//concatenate token, and a space
5) free allocated memory
new_str now contains sentence without occurrences of str_to_remove.
Here is a demo using this set of steps (pretty much)
int delete(char *str, char *str_to_remove)
{
char *buf;
char *new_str;
new_str = calloc(strlen(str)+1, sizeof(char));
buf = strtok(str, " \t\n");
while(buf)
{
if(strcmp(buf, str_to_remove) != 0)
{
strcat(new_str, buf);
strcat(new_str, " ");
}
buf = strtok(NULL, " \t\n");
}
printf("%s\n", new_str);
free(new_str);
getchar();
return 0;
}
int main(void)
{
delete("this sentence had a withh bad withh word", "withh");
return 0;
}