#include <stdio.h>
int
main() {
char string[] = "my name is geany";
int length = sizeof(string)/sizeof(char);
printf("%i", length);
int i;
for ( i = 0; i<length; i++ ) {
}
return 0;
}
if i want to print "my" "name" "is" and "geany" separate then what do I do. I was thinking to use a delimnator but i dont know how to do it in C
start with a pointer to the begining of the string
iterate character by character, looking for your delimiter
each time you find one, you have a string from the last position of the length in difference - do what you want with that
set the new start position to the delimiter + 1, and the go to step 2.
Do all these while there are characters remaining in the string...
I needed to do this because the environment was working in had a restricted library that lacked strtok. Here's how I broke up a hyphen-delimited string:
b = grub_strchr(a,'-');
if (!b)
<handle error>
else
*b++ = 0;
c = grub_strchr(b,'-');
if (!c)
<handle error>
else
*c++ = 0;
Here, a begins life as the compound string "A-B-C", after the code executes, there are three null-terminated strings, a, b, and c which have the values "A", "B" and "C". The <handle error> is a place-holder for code to react to missing delimiters.
Note that, like strtok, the original string is modified by replacing the delimiters with NULLs.
This breaks a string at newlines and trims whitespace for the reported strings. It does not modify the string like strtok does, which means this can be used on a const char* of unknown origin while strtok cannot. The difference is begin/end are pointers to the original string chars, so aren't null terminated strings like strtok gives. Of course this uses a static local so isn't thread safe.
#include <stdio.h> // for printf
#include <stdbool.h> // for bool
#include <ctype.h> // for isspace
static bool readLine (const char* data, const char** beginPtr, const char** endPtr) {
static const char* nextStart;
if (data) {
nextStart = data;
return true;
}
if (*nextStart == '\0') return false;
*beginPtr = nextStart;
// Find next delimiter.
do {
nextStart++;
} while (*nextStart != '\0' && *nextStart != '\n');
// Trim whitespace.
*endPtr = nextStart - 1;
while (isspace(**beginPtr) && *beginPtr < *endPtr)
(*beginPtr)++;
while (isspace(**endPtr) && *endPtr >= *beginPtr)
(*endPtr)--;
(*endPtr)++;
return true;
}
int main (void) {
const char* data = " meow ! \n \r\t \n\n meow ? ";
const char* begin;
const char* end;
readLine(data, 0, 0);
while (readLine(0, &begin, &end)) {
printf("'%.*s'\n", end - begin, begin);
}
return 0;
}
Output:
'meow !'
''
''
'meow ?'
use strchr to find the space.
store a '\0' at that location.
the word is now printfable.
repeat
start the search at the position after the '\0'
if nothing is found then print the last word and break out
otherwise, print the word, and continue the loop
Reinventing the wheel is often a bad idea. Learn to use implementation functions is also a good training.
#include <string.h>
/*
* `strtok` is not reentrant, so it's thread unsafe. On POSIX environment, use
* `strtok_r instead.
*/
int f( char * s, size_t const n ) {
char * p;
int ret = 0;
while ( p = strtok( s, " " ) ) {
s += strlen( p ) + 1;
ret += puts( p );
}
return ret;
}
Related
I am writing my own trim() in C. There is a structure which contains all string values, the structure is getting populated from the data coming from a file which contains spaces before and after the beginning of a word.
char *trim(char *string)
{
int stPos,endPos;
int len=strlen(string);
for(stPos=0;stPos<len && string[stPos]==' ';++stPos);
for(endPos=len-1;endPos>=0 && string[endPos]==' ';--endPos);
char *trimmedStr = (char*)malloc(len*sizeof(char));
strncpy(trimmedStr,string+stPos,endPos+1);
return trimmedStr;
}
int main()
{
char string1[]=" a sdf ie ";
char *string =trim(string1);
printf("%s",string);
return 0;
}
Above code is working fine, but i don't want to declare new variable that stores the trimmed word. As the structure contains around 100 variables.
Is there any way to do somthing like below where I dont need any second variable to print the trimmed string.
printf("%s",trim(string1));
I believe above print can create dangling pointer situation.
Also, is there any way where I don't have to charge original string as well, like if I print trim(string) it will print trimmed string and when i print only string, it will print original string
elcuco was faster. but it's done so here we go:
char *trim(char *string)
{
char *ptr = NULL;
while (*string == ' ') string++; // chomp away space at the start
ptr = string + strlen(string) - 1; // jump to the last char (-1 because '\0')
while (*ptr == ' '){ *ptr = '\0' ; ptr--; } ; // overwrite with end of string
return string; // return pointer to the modified start
}
If you don't want to alter the original string I'd write a special print instead:
void trim_print(char *string)
{
char *ptr = NULL;
while (*string == ' ') string++; // chomp away space at the start
ptr = string + strlen(string) - 1; // jump to the last char (-1 because '\0')
while (*ptr == ' '){ ptr--; } ; // find end of string
while (string <= ptr) { putchar(*string++); } // you get the picture
}
something like that.
You could the original string in order to do this. For trimming the prefix I just advance the pointer, and for the suffix, I actually add \0. If you want to keep the original starting as is, you will have to move memory (which makes this an O(n^2) time complexity solution, from an O(n) I provided).
#include <stdio.h>
char *trim(char *string)
{
// trim prefix
while ((*string) == ' ' ) {
string ++;
}
// find end of original string
char *c = string;
while (*c) {
c ++;
}
c--;
// trim suffix
while ((*c) == ' ' ) {
*c = '\0';
c--;
}
return string;
}
int main()
{
char string1[] = " abcdefg abcdf ";
char *string = trim(string1);
printf("String is [%s]\n",string);
return 0;
}
(re-thinking... is it really O(n^2)? Or is it O(2n) which is a higher O(n)...? I guess depending on implementation)
You can modify the function by giving the output in the same input string
void trim(char *string)
{
int i;
int stPos,endPos;
int len=strlen(string);
for(stPos=0;stPos<len && string[stPos]==' ';++stPos);
for(endPos=len-1;endPos>=0 && string[endPos]==' ';--endPos);
for (i=0; i<=(endPos-stPos); i++)
{
string[i] = string[i+stPos];
}
string[i] = '\0'; // terminate the string and discard the remaining spaces.
}
...is there any way where i don't have to charge original string as well, like if i do trim(string) it will print trimmed string and when i print only string, it will print original string – avinashse 8 mins ago
Yes, though it gets silly.
You could modify the original string.
trim(string);
printf("trimmed: %s\n", string);
The advantage is you have the option of duplicating the string if you want to retain the original.
char *original = strdup(string);
trim(string);
printf("trimmed: %s\n", string);
If you don't want to modify the original string, that means you need to allocate memory for the modified string. That memory then must be freed. That means a new variable to hold the pointer so you can free it.
char *trimmed = trim(original);
printf("trimmed: %s\n", trimmed);
free(trimmed);
You can get around this by passing a function pointer into trim and having trim manage all the memory for you.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void trim(char *string, void(*func)(char *) )
{
// Advance the pointer to the first non-space char
while( *string == ' ' ) {
string++;
}
// Shrink the length to the last non-space char.
size_t len = strlen(string);
while(string[len-1]==' ') {
len--;
}
// Copy the string to stack memory
char trimmedStr[len + 1];
strncpy(trimmedStr,string, len);
// strncpy does not add a null byte, add it ourselves.
trimmedStr[len] = '\0';
// pass the trimmed string into the user function.
func(trimmedStr);
}
void print_string(char *str) {
printf("'%s'\n", str);
}
int main()
{
char string[]=" a sdf ie ";
trim(string, print_string);
printf("original: '%s'\n", string);
return 0;
}
Ta da! One variable, the original is left unmodified, no memory leaks.
While function pointers have their uses, this is a bit silly.
It's C. Get used to managing memory. ¯\_(ツ)_/¯
Also, is there any way where I don't have to charge original string as
well, like if I print trim(string) it will print trimmed string and
when i print only string, it will print original string
Yes you can, but you cannot allocate new memory in the trim function as you will not be holding the return memory.
You can have a static char buffer in the trim function and operate on it.
Updated version of #elcuco answer.
#include <stdio.h>
char *trim(char *string)
{
static char buff[some max length];
// trim prefix
while ((*string) == ' ' ) {
string++;
}
// find end of original string
int i = 0;
while (*string) {
buff[i++] = *string;
string++;
}
// trim suffix
while ((buff[i]) == ' ' ) {
buff[i] = '\0';
i--;
}
return buff;
}
int main()
{
char string1[] = " abcdefg abcdf ";
char *string = trim(string1);
printf("String is [%s]\n",string);
return 0;
}
With this you don't need to worry about holding reference to trim function return.
Note: Previous values of buff will be overwritten with new call to trim function.
If you don't want to change the original, then you will need to make a copy, or pass a second array of sufficient size as a parameter to your function for filling. Otherwise a simple in-place trmming is fine -- so long as the original string is mutable.
An easy way to approach trimming on leading and trailing whitespace is to determine the number of leading whitespace characters to remove. Then simply use memmove to move from the first non-whitespace character back to the beginning of the string (don't forget to move the nul-character with the right portion of the string).
That leaves only removing trailing whitespace. An easy approach there is to loop from the end of the string toward the beginning, overwriting each character of trailing whitespace with a nul-character until your first non-whitespace character denoting the new end of string is found.
A simple implementation for that could be:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define DELIM " \t\n" /* whitespace constant delimiters for strspn */
/** trim leading and trailing whitespace from s, (s must be mutable) */
char *trim (char *s)
{
size_t beg = strspn (s, DELIM), /* no of chars of leading whitespace */
len = strlen (s); /* length of s */
if (beg == len) { /* string is all whitespace */
*s = 0; /* make s the empty-string */
return s;
}
memmove (s, s + beg, len - beg + 1); /* shift string to beginning */
for (int i = (int)(len - beg - 1); i >= 0; i--) { /* loop from end */
if (isspace(s[i])) /* checking if char is whitespace */
s[i] = 0; /* overwrite with nul-character */
else
break; /* otherwise - done */
}
return s; /* Return s */
}
int main (void) {
char string1[] = " a sdf ie ";
printf ("original: '%s'\n", string1);
printf ("trimmed : '%s'\n", trim(string1));
}
(note: additional intervening whitespace was added to your initial string to show that multiple intervening whitespace is left unchanged, the output is single-quoted to show the remaining text boundaries)
Example Use/Output
$ ./bin/strtrim
original: ' a sdf ie '
trimmed : 'a sdf ie'
Look things over and let me know if you have further questions.
#include <stdio.h>
int
main() {
char string[] = "my name is geany";
int length = sizeof(string)/sizeof(char);
printf("%i", length);
int i;
for ( i = 0; i<length; i++ ) {
}
return 0;
}
if i want to print "my" "name" "is" and "geany" separate then what do I do. I was thinking to use a delimnator but i dont know how to do it in C
start with a pointer to the begining of the string
iterate character by character, looking for your delimiter
each time you find one, you have a string from the last position of the length in difference - do what you want with that
set the new start position to the delimiter + 1, and the go to step 2.
Do all these while there are characters remaining in the string...
I needed to do this because the environment was working in had a restricted library that lacked strtok. Here's how I broke up a hyphen-delimited string:
b = grub_strchr(a,'-');
if (!b)
<handle error>
else
*b++ = 0;
c = grub_strchr(b,'-');
if (!c)
<handle error>
else
*c++ = 0;
Here, a begins life as the compound string "A-B-C", after the code executes, there are three null-terminated strings, a, b, and c which have the values "A", "B" and "C". The <handle error> is a place-holder for code to react to missing delimiters.
Note that, like strtok, the original string is modified by replacing the delimiters with NULLs.
This breaks a string at newlines and trims whitespace for the reported strings. It does not modify the string like strtok does, which means this can be used on a const char* of unknown origin while strtok cannot. The difference is begin/end are pointers to the original string chars, so aren't null terminated strings like strtok gives. Of course this uses a static local so isn't thread safe.
#include <stdio.h> // for printf
#include <stdbool.h> // for bool
#include <ctype.h> // for isspace
static bool readLine (const char* data, const char** beginPtr, const char** endPtr) {
static const char* nextStart;
if (data) {
nextStart = data;
return true;
}
if (*nextStart == '\0') return false;
*beginPtr = nextStart;
// Find next delimiter.
do {
nextStart++;
} while (*nextStart != '\0' && *nextStart != '\n');
// Trim whitespace.
*endPtr = nextStart - 1;
while (isspace(**beginPtr) && *beginPtr < *endPtr)
(*beginPtr)++;
while (isspace(**endPtr) && *endPtr >= *beginPtr)
(*endPtr)--;
(*endPtr)++;
return true;
}
int main (void) {
const char* data = " meow ! \n \r\t \n\n meow ? ";
const char* begin;
const char* end;
readLine(data, 0, 0);
while (readLine(0, &begin, &end)) {
printf("'%.*s'\n", end - begin, begin);
}
return 0;
}
Output:
'meow !'
''
''
'meow ?'
use strchr to find the space.
store a '\0' at that location.
the word is now printfable.
repeat
start the search at the position after the '\0'
if nothing is found then print the last word and break out
otherwise, print the word, and continue the loop
Reinventing the wheel is often a bad idea. Learn to use implementation functions is also a good training.
#include <string.h>
/*
* `strtok` is not reentrant, so it's thread unsafe. On POSIX environment, use
* `strtok_r instead.
*/
int f( char * s, size_t const n ) {
char * p;
int ret = 0;
while ( p = strtok( s, " " ) ) {
s += strlen( p ) + 1;
ret += puts( p );
}
return ret;
}
I'm a beginner at C and I'm stuck on a simple problem. Here it goes:
I have a string formatted like this: "first1:second1\nsecond2\nfirst3:second3" ... and so on.
As you can see from the the example the first field is optional ([firstx:]secondx).
I need to get a resulting string which contains only the second field. Like this: "second1\nsecond2\nsecond3".
I did some research here on stack (string splitting in C) and I found that there are two main functions in C for string splitting: strtok (obsolete) and strsep.
I tried to write the code using both functions (plus strdup) without success. Most of the time I get some unpredictable result.
Better ideas?
Thanks in advance
EDIT:
This was my first try
int main(int argc, char** argv){
char * stri = "ciao:come\nva\nquialla:grande\n";
char * strcopy = strdup(stri); // since strsep and strtok both modify the input string
char * token;
while((token = strsep(&strcopy, "\n"))){
if(token[0] != '\0'){ // I don't want the last match of '\n'
char * sub_copy = strdup(token);
char * sub_token = strtok(sub_copy, ":");
sub_token = strtok(NULL, ":");
if(sub_token[0] != '\0'){
printf("%s\n", sub_token);
}
}
free(sub_copy);
}
free(strcopy);
}
Expected output: "come", "si", "grande"
Here's a solution with strcspn:
#include <stdio.h>
#include <string.h>
int main(void) {
const char *str = "ciao:come\nva\nquialla:grande\n";
const char *p = str;
while (*p) {
size_t n = strcspn(p, ":\n");
if (p[n] == ':') {
p += n + 1;
n = strcspn(p , "\n");
}
if (p[n] == '\n') {
n++;
}
fwrite(p, 1, n, stdout);
p += n;
}
return 0;
}
We compute the size of the initial segment not containing : or \n. If it's followed by a :, we skip over it and get the next segment that doesn't contain \n.
If it's followed by \n, we include the newline character in the segment. Then we just need to output the current segment and update p to continue processing the rest of the string in the same way.
We stop when *p is '\0', i.e. when the end of the string is reached.
Can I use the strstr function to match exact word? For example, let's say I have the word hello, and an input string line:
if
char* line = "hellodarkness my old friend";
and I use
result = strstr(line, "hello");
result will match (be not NULL), however I want to match only the exact word "hello" (so that "hellodarkness" would not match) and result will be NULL.
Is it possible to do this using strstr or do I have to use fscan and scan the line word by word and check for matches?
Here is a generic function for your purpose. It returns a pointer to the first match or NULL if none can be found:
#include <ctype.h>
#include <string.h>
char *word_find(const char *str, const char *word) {
const char *p = NULL;
size_t len = strlen(word);
if (len > 0) {
for (p = str; (p = strstr(p, word)) != NULL; p++) {
if (p == str || !isalnum((unsigned char)p[-1])) {
if (!isalnum((unsigned char)p[len]))
break; /* we have a match! */
p += len; /* next match is at least len+1 bytes away */
}
}
}
return p;
}
I would:
check if string is in sentence
if found at start (same pointer as line), add the length of the word and check if alphanumerical char found. If not (or null-terminated), then match
if found anywhere else, add the extra "no alphanum before" test
code:
#include <stdio.h>
#include <strings.h>
#include <ctype.h>
int main()
{
const char* line = "hellodarkness my old friend";
const char *word_to_find = "hello";
char* p = strstr(line,word_to_find);
if ((p==line) || (p!=NULL && !isalnum((unsigned char)p[-1])))
{
p += strlen(word_to_find);
if (!isalnum((unsigned char)*p))
{
printf("Match\n");
}
}
return 0;
}
here it doesn't print anything, but insert a punctuation/space before/after or terminate the string after "hello" and you'll get a match. Also, you won't get a match by inserting alphanum chars before hello.
EDIT: the above code is nice when there's only 1 "hello" but fails to find the second "hello" in "hellohello hello". So we have to insert a loop to look for the word or NULL, advancing p each time, like this:
#include <stdio.h>
#include <strings.h>
#include <ctype.h>
int main()
{
const char* line = " hellohello hello darkness my old friend";
const char *word_to_find = "hello";
const char* p = line;
for(;;)
{
p = strstr(p,word_to_find);
if (p == NULL) break;
if ((p==line) || !isalnum((unsigned char)p[-1]))
{
p += strlen(word_to_find);
if (!isalnum((unsigned char)*p))
{
printf("Match\n");
break; // found, quit
}
}
// substring was found, but no word match, move by 1 char and retry
p+=1;
}
return 0;
}
Since strstr() returns the pointer to the starting location of the substring that you want to identify, then you can use strlen(result) the check if it is a substring of longer string or the isolated string that you are looking for. if strlen(result) == strlen("hello"), then it ends correctly. If it ends with a space or punctuation (or some other delimiter), then it is also isolated at the end. You would also need to check if the start of the substring is at the beginning of the "long string" or preceded by a blank, punctuation, or other delimiter.
I have a GtkEntry where the user has to enter an IP number or a hostname. When the button is pressed what the user typed into the entry is added to a char. How can I programmatically check if this char contains spaces, the newline character or the tab character? I don't need to remove them, just to know if they exist. Thanks in advance!
Take a look at character classification routines: man isspace.
Create a char array containing the characters of interest. Then use strchr() to search for the presence of the char in the string.
char charSet[] = { ' ', '\n', '\t', 0 };
char c;
// code that puts a character in c
if (strchr(charSet, c) != NULL)
{
// it is one of the set
}
The function you are looking for is strpbrk().
#include <stdio.h>
#include <string.h>
int check_whitespace (char *str)
{
char key[] = { ' ', '\n', '\t', 0 };
return strpbrk (str, key);
}
Let us suppose you mean that what is typed into the GtkEntry is added to an array of char (a string, in C terminology, provided that it is null terminated). Then to check if that array of char contains at least one or more of "space" characters (according to the locale, so we use isspace),
char *array;
int i;
//..
bool contains_space = false;
for(i = 0; i < strlen(array); i++) {
if ( isspace(array[i]) ) {
contains_space = true;
break;
}
}
// return contains_space
which can be turned into a function for example.
You might consider a function such as the following which counts the number of whitespace characters in the given string giving a positive integer is any are found (i.e. TRUE), zero if none are found (i.e. FALSE) and -1 on error.
#include <ctype.h>
static int
ws_count(char *s)
{
int n = -1;
if (s != NULL) {
char *p;
for (n = 0, p = s; *p != '\0'; p++) {
if (isspace(*p)) {
n++;
}
}
}
return n;
}