How do I check if a string contains a certain character? - c

I'm fairly new to C programming, how would I be able to check that a string contains a certain character for instance, if we had:
void main(int argc, char* argv[]){
char checkThisLineForExclamation[20] = "Hi, I'm odd!"
int exclamationCheck;
}
So with this, how would I set exclamationCheck with a 1 if "!" is present and 0 if it's not? Many thanks for any assistance given.

By using strchr(), like this for example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "Hi, I'm odd!";
int exclamationCheck = 0;
if(strchr(str, '!') != NULL)
{
exclamationCheck = 1;
}
printf("exclamationCheck = %d\n", exclamationCheck);
return 0;
}
Output:
exclamationCheck = 1
If you are looking for a laconic one liner, then you could follow #melpomene's approach:
int exclamationCheck = strchr(str, '!') != NULL;
If you are not allowed to use methods from the C String Library, then, as #SomeProgrammerDude suggested, you could simply iterate over the string, and if any character is the exclamation mark, as demonstrated in this example:
#include <stdio.h>
int main(void)
{
char str[] = "Hi, I'm odd";
int exclamationCheck = 0;
for(int i = 0; str[i] != '\0'; ++i)
{
if(str[i] == '!')
{
exclamationCheck = 1;
break;
}
}
printf("exclamationCheck = %d\n", exclamationCheck);
return 0;
}
Output:
exclamationCheck = 0
Notice that you could break the loop when at least one exclamation mark is found, so that you don't need to iterate over the whole string.
PS: What should main() return in C and C++? int, not void.

You can use plain search for ! character with
Code
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "Hi, I'm odd!";
int exclamationCheck = 0;
int i=0;
while (str[i]!='\0'){
if (str[i]=='!'){
exclamationCheck = 1;
break;
}
i++;
}
printf("exclamationCheck = %d\n", exclamationCheck);
return 0;
}

Related

How to Tokenize String without using strtok()

I'm trying to tokenize a string without using a strtok().
When I run characters of string, it will print in each line.
For instance, when I run:
printfTokens("Hello from other side!");
The output should be:
Hello
from
other
side!
As I'm just learning C, I'm stuck for hours on how to implement this program. So far, I only know the basics and playing around with not (still haven't learned any calloc, malloc, etc).
So far I have this code, but the output does not print anything.
#include <stdio.h>
#include <string.h>
#define MAX_WORD 100
void printfTokens(char *inputString) {
int i;
/*int inputStringLength;
for(i = 0; inputString[i] != '/0'; i++) {
inputStringLength++;
}*/
while(inputString[i] != '\0') {
char testing[MAX_WORD];
while(inputString[i] != ' ') {
testing[inputString[i]]++;
i++;
}
printf("%s", testing);
i++;
}
}
int main() {
printfTokens("TESTING ONE! TWO! THREE!");
return 0;
}
You do not initialize the variable i.
while(inputString[i] != '\0') can be written while(inputString[i]).
testing[inputString[i]]++ makes sense to count the number of occurrences of a given character from inputString, but it does not make sense to print it. You may want to do something like:
while(1)
{
char testing[MAX_WORD], *t=testing;
while(inputString[i]&&(inputString[i]!=' '))
*t++=inputString[i++];
if (t>testing) printf("%s", testing);
if (!inputString[i]) break;
i++;
}
It would be better to name MAX_WORD_LENGTH instead of MAX_WORD.
These are a few problems in your code.
Sample tokenization function.
size_t tokenize(const char *inputString, const char *delim, char **argv, size_t maxtokens)
{
size_t ntokens = 0;
char *tokenized = strdup(inputString);
if(tokenized)
{
argv[0] = tokenized;
while(*tokenized)
{
if(strchr(delim, *tokenized))
{
*tokenized = 0;
ntokens++;
if(ntokens == maxtokens - 1)
{
break;
}
argv[ntokens] = tokenized + 1;
}
tokenized++;
}
}
return ntokens + 1;
}
int main()
{
char *tokens[10];
size_t ntokens = tokenize("TESTING ONE! TWO! THREE!", " ", tokens , 10);
for(size_t i = 0; i < ntokens; i++)
{
printf("Token[%zu] = `%s`\n", i, tokens[i]);
}
free(tokens[0]);
return 0;
}
https://godbolt.org/z/znv8PszG6

How to split with multiple delimiters in C

I have this line of text:
32+-#3#2-#3#3
I need to separate numbers from each other. So basically the result would be like this:
3
2+-
3
2-
3
3
This is my code but it's not working properly because I have numbers with two digits:
#include <stdio.h>
#include <string.h>
int main(void) {
char string[50] = "32-#3#2-#3#3";
// 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;
}
You can't do it with strtok (alone), because there is no delimiter between the numbers you want to split. It's easier without strtok, just print what you want printed and add a separator unless a character which belongs to the token follows:
#include <stdio.h>
int main()
{
char string[] = "32+-#3#2-#3#3";
for (char *token = string; *token; ++token)
if ('0'<=*token && *token<='9' || *token=='+' || *token=='-')
{
putchar(*token);
if (token[1]!='+' && token[1]!='-') putchar('\n');
}
}
If you consider this too easy, you can use a regular expression to match the tokens:
#include <stdio.h>
#include <regex.h>
int main()
{
char *string = "32+-#3#2-#3#3";
regex_t reg;
regcomp(&reg, "[0-9][+-]*", 0);
regmatch_t match = {0};
while (regexec(&reg, string+=match.rm_eo, 1, &match, 0) == 0)
printf("%.*s\n", (int)(match.rm_eo-match.rm_so), string+match.rm_so);
}
There is a simple way to achieve this, but in C is a bit more complicated since we don't have vector as in C++ but I can suggest a pure C implementation which can be improved:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void split_ss(const char* src,const char* pattern, char** outvec, size_t* outsize)
{
const size_t pat_len = strlen(pattern);
char* begin = (char*) src;
const char* next = begin;
if ((begin = strstr((const char*)begin, pattern)) != 0x00) {
unsigned int size = begin - next;
*outvec = malloc(sizeof(char) * size);
memcpy(*outvec , next, size);
outvec++;
(*outsize)+=1;
split_ss(begin+pat_len, pattern, outvec, outsize);
} else {
unsigned int size = &src[strlen(src)-1] - next + 1;
*outvec = malloc(sizeof(char) * size);
memcpy(*outvec, next, size);
(*outsize) += 1;
}
}
int main()
{
char* outdata[64] = {0};
size_t size, i=0;
split_ss("32+-#3#2-#3#3", "#", outdata, &size);
for(i=0; i < size; i++) {
printf("[%s]\r\n", outdata[i]);
}
// make sure to free it
return 0;
}
strstr is used to split by string rather than a character. Also output is a poorman 2D array with out size to iterate it and don't forget to free it.
strtok() is not the right tool for you purpose... As a matter of fact strtok() is rarely the right tool for any purpose because of its tricky semantics and side effects.
A simple loop will do:
#include <stdio.h>
int main(void) {
char string[50] = "32+-#3#2-#3#3";
for (char *p = string; *p; p++) {
if (*p == '#')
continue;
putchar(*p);
while (p[1] == '+' || p[1] == '-')
putchar(*++p);
putchar('\n');
}
return 0;
}

Whitespace replace in C language

What is the right way to replace a white space with _ in string passCode with 2 characters?
In the end it should input/output: (a ) → (a_). Is there a way to do this using the isspace?
isspace(passCode[2]) == 0;
Check if the character is a space if yes, then replace it with _.
For example:
#include <stdio.h>
#include <ctype.h>
int main ()
{
int i=0;
unsigned char str[]="a ";
while (str[i])
{
if (isspace(str[i]))
str[i]='_';
i++;
}
printf("%s\n",str);
return 0;
}
A simple manner for character substitution is simply to create a pointer to the string and then check each character in the string for value x and replace it with character y as you go. An example would be:
#include <stdio.h>
int main (void)
{
char passcode[] = "a ";
char *ptr = passcode;
while (*ptr)
{
if (*ptr == ' ')
*ptr = '_';
ptr++;
}
printf ("\n passcode: %s\n\n", passcode);
return 0;
}
output:
$ ./bin/chrep
passcode: a_
The best way to do this is:
#include <stdio.h>
void replace_spaces(char *str)
{
while (*str)
{
if (*str == ' ')
*str = '_';
str++;
}
}
int main(int ac, int av)
{
char *pass = 'pas te st';
replace_spaces(pass);
printf("%s\n", pass);
return (0);
}
pass i now equal to 'pas_te_st'.

Updating string until period is found in C

In this function I am going to be receiving char * words such as
person.vet.blah
and
word.friends.joe
I want to extract the first word. So for the first one I want to extract
person
and the second one I want to extract
word
How can I correctly do this? Here is my code:
char *separate_name(char *machine_name)
{
//iterate until you find period. then return
char absolute_name[1000];
int i;
for (i =0; i < strlen(machine_name); i++)
{
if (machine_name[i] == '.')
absolute_name[i] = machine_name[i];
}
return absolute_name;
}
This is just segfaulting. Any ideas what I should be doing? machine_name is going to be the "person.vet.blah" and then return absolute_name which would be "person"
Fixing your code
As others have pointed out, you can't use absolute_name outside of the function in which it was defined. This is because you're when you return the variable from your function, all that is being returned is a pointer to the beginning of the array. Outside the function, the array itself no longer exists, so the pointer is invalid and you get a segfault if you try and dereference it.
You can get around this by using malloc. Don't forget to free the memory you have allocated when you are done using it.
By the way, as well as changing your loop to a while, I also fixed the check (you were checking machine_name[i] == '.', the opposite to what you wanted).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *separate_name(char *machine_name)
{
// allocate memory on the heap
char *absolute_name = malloc(strlen(machine_name)+1);
int i = 0;
while (i < strlen(machine_name) && machine_name[i] != '.') {
absolute_name[i] = machine_name[i];
++i;
}
absolute_name[i] = '\0';
return absolute_name;
}
int main()
{
char name1[] = "person.vet.blah";
char *first1 = separate_name(name1);
if (first1 != NULL) {
printf("%s\n", first1);
free(first1);
}
char name2[] = "word.friends.joe";
char *first2 = separate_name(name2);
if (first2 != NULL) {
printf("%s\n", first2);
free(first2);
}
return 0;
}
A better alternative
strtok is the perfect tool for the job:
#include <stdio.h>
#include <string.h>
char *separate_name(char *machine_name)
{
return strtok(machine_name, ".");
}
int main()
{
char name1[] = "person.vet.blah";
char *first1 = separate_name(name1);
if (first1 != NULL) printf("%s\n", first1);
char name2[] = "word.friends.joe";
char *first2 = separate_name(name2);
if (first2 != NULL) printf("%s\n", first2);
return 0;
}
As pointed out in the comments (thanks #John), strtok modifies the string that is passed to it (it replaces the delimiter . by the \0 null byte to mark the end of the string). This isn't a problem here but is something to be aware of.
Output using either program:
person
word
#include <stdio.h>
char *separate_name(const char *machine_name){
static char absolute_name[1000];
int i;
for (i =0; i < sizeof(absolute_name)-1 ; i++){
if(machine_name[i] == '.' || machine_name[i] == '\0'){
absolute_name[i] = '\0';
break;
} else {
absolute_name[i] = machine_name[i];
}
}
return absolute_name;
}
int main(void){
printf("%s\n", separate_name("person.vet.blah"));
printf("%s\n", separate_name("word.friends.joe"));
return 0;
}

Getting a segmentation fault in my code

My code is giving me a segmentation fault. I'm 99% sure the fault is stemming from my lousy code construction.
#include <stdio.h>
#include <assert.h>
#include <string.h>
int decToBit(unsigned int I, char *str){
str = "";
int currentVal = I;
do{
if(I%2 == 0)
strcat(str,"0");
else
strcat(str,"1");
} while(currentVal > 0);
return(0);
}
You need to make sure that there is enough space in str to add the extra characters:
char myStr[200];
myStr[0] = '\0'; // make sure you start with a "zero length" string.
strcpy(myStr, str);
and then use myStr where you were using str.
As it is, the statement
str="";
points str to a const char* - that is a string you can read but not write.
Incidentally the call signature for main is
int main(int argc, char *argv[])
in other words, you need a pointer to a pointer to char. If I am not mistaken, you would like to do the following (a bit of mind reading here):
Every odd argument gets a 1 added; every even argument gets a 0 added.
If my mind reading trick worked, then you might want to try this:
#include <stdio.h>
#include <string.h>
int main(int argc, char * argv[]) {
char temp[200];
temp[0] = '\0';
int ii;
for(ii = 0; ii < argc; ii++) {
strncpy(temp, argv[ii], 200); // safe copy
if(ii%2==0) {
strcat(temp, "0");
}
else {
strcat(temp, "1");
}
printf("%s\n", temp);
}
}
edit just realized you edited the question and now your purpose is much clearer.
Modified your function a bit:
int decToBit(unsigned int I, char *str){
str[0] = '\0';
char *digit;
do
{
digit = "1";
if ( I%2 == 0) digit = "0";
strcat(str, digit);
I>>=1;
} while (I != 0);
return(0);
}
It seems to work...
In do-while loop you should increment the value of currentVal. Otherwise it will be an infinity loop and you will end up with Segmentation fault.
Initialize str[0] properly.
Divide I by 2 each loop.
But then the string will be in a little endian order. Doubt that was intended?
int decToBit(unsigned int I, char *str) {
str[0] = '\0';
do {
if (I%2 == 0)
strcat(str,"0");
else
strcat(str,"1");
I /= 2;
} while(I > 0);
return(0);
}
// call example
char buf[sizeof(unsigned)*CHAR_BIT + 1];
decToBit(1234567u, buf);
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
char *decToBit(unsigned int I, char *str){
int bit_size = CHAR_BIT * sizeof(I);
str += bit_size;
*str = 0;
do{
*--str = "01"[I & 1];
}while(I>>=1);
return str;
}
int main(){
char bits[33];
printf("%s\n", decToBit(0, bits));
printf("%s\n", decToBit(-1, bits));
printf("%s\n", decToBit(5, bits));
return 0;
}

Resources