Parse a String in C - c

Using just C
I would like to parse a string and:
count the occurrences of a character in a string (for example, count all the 'e's in a passed in string)
Once counted (or even as I am counting) replace the e's with 3's

OK, you're either lazy, or stuck, assuming stuck.
You need a function with a signature something like
int ReplaceCharInString(char* string, char charToFind, char charThatReplaces)
{
}
Inside the function you need
To declare an integer to count the
occurrences
A loop that moves from the start of
the string to it's end
inside the loop, an if statement to
check is the current char the
charToFind,
statements to increment the count of
occurrences and perform the
replacement
After the loop, you need to return
the count of occurrences

This function will take a string, replace every 'e' with '3', and return the number of times it performed the substitution. It's safe, it's clean, it's fast.
int e_to_three(char *s)
{
char *p;
int count = 0;
for (p = s; *p; ++p) {
if (*p == 'e') {
*p = '3';
count++;
}
}
return count;
}

Here's a shell to get you started. Ask here if you need any help.
#include <string.h>
#include <stdio.h>
int main(){
const char* string = "hello world";
char buffer[256];
int e_count = 0;
char* walker;
// Copy the string into a workable buffer
strcpy(buffer,string);
// Do the operations
for(walker=buffer;*walker;++walker){
// Use *walker to read and write the current character
}
// Print it out
printf("String was %s\nNew string is %s\nThere were %d e's\n",string,buffer,e_count);
}

In general, it's better use a standard library function rather than rolling your own. And, as it just so happens, there is a standard library function that searches a string for a character and returns a pointer to it. (It deals with a string, so look among the functions that have the prefix "str") (The library function will almost certainly be optimized to use specialized CPU opcodes for the task, that hand written code would not)
Set a temp pointer (say "ptr") to the start of the string.
In a loop, call the function above using ptr as the parameter, and setting it to the return value.
Increment a counter.
Set the character at the pointer to "3" break when 'e' is not found.

Some of you guys are starting in the middle.
A better start would be
char *string = "hello world";
Assert(ReplaceCharInString(string, 'e', '3') == 1);
Assert(strcmp(string, "h3llo world") == 0);

Related

function returning a string of zeros in c

i trying to create a function that return an array of zeros us a char array
and print this array in a file text but when i return a string an addition char was returned
this the text file string the program wrote
this my fuction :
char *zeros_maker (int kj,int kj1)
{
char *zeros;
zeros = (char *) malloc(sizeof(char)*(kj-kj1));
int i;
for(i =0;i<kj-kj1;i++)
zeros[i]='0';
printf("%s\n",zeros);
return zeros;
}
the instruction i used when i printed in the file
fprintf(pFile,"%c%s%c &",34,zeros_maker(added_zeros,0),34);
Thanks in advance
'0' in C is the value of the encoding used for the digit zero. This is not allowed to have the value 0 by the C standard.
You need to add a NUL-terminator '\0' to the end of the char array, in order for the printf function to work correctly.
Else you run the risk of it running past the end of the char array, with undefined results.
Finally, don't forget to free the allocated memory at some point in your program.
Read about how string in C are meant to be terminated.
Each string terminates with the null char '\0' (the NULL symbol ASCII value 0, not to be confused with the char '0' that has ASCII value 48). It identifies the end of the string.
zeros[kj-kj1]='\0';
Plus check always if you are accessing an element out of bound. In this case it happens if kj1> kj
Instead of for loop, you may get hand of memset.
char* zeros_maker(int kj,int kj1)
{
int len=kj-kj1;
char *zeros=malloc(sizeof(char)*(len));
memset(zeros,'0',len-1);
zeros[len-1]=0;
printf("%s\n",zeros);
//fflush(stdout);
return zeros;
}
Or if you are not fan of C-style string, and it's going to be ASCII only, following could be used too. Just be careful what your are doing this way.
char* zeros_maker_pascal_form(int kj,int kj1)
{
int len=kj-kj1;
char *zeros=malloc(sizeof(char)*(len));
memset(zeros,'0',len);
for(int a=0;a<len;a++){
printf("%c",zeros[a]);
}
printf("\n");
//fflush(stdout);
return zeros;
}
Your code has a few basic issues, the main one is that it fails to terminate the string (and include space for the terminator).
Here's a fixed and cleaned-up version:
char * zeros_maker(size_t length)
{
char *s = malloc(length + 1);
if(s != NULL)
{
memset(s, '0', length);
s[length - 1] = '\0';
}
return s;
}
This has the following improvements over your code:
It simplifies the interface, just taking the number of zeroes that should be returned (the length of the returned string). Do the subtraction at the call site, where those two values make sense.
No cast of the return value from malloc(), and no scaling by sizeof (char) since I consider that pointless.
Check for NULL being returned by malloc() before using the memory.
Use memset() to set a range of bytes to a single value, that's a standard C function and much easier to know and verify than a custom loop.
Terminate the string, of course.
Call it like so:
char *zs = zeros_maker(kj - kj1);
puts(s);
free(s);
Remember to free() the string once you're done with it.

Is using input parameters instead of local variables more efficient in C?

Consider the two functions below. Both functions compute the number of times a character appears in a string with a specified length.
int str_get_num_occurrences1(char * str, char c, unsigned int len){
if (!len)
len = strlen(str);
int res = 0;
int n = len;
for ( ; n--; )
if (str[n] == c)
res++;
return res;
}
int str_get_num_occurrences2(char * str, char c, unsigned int len){
int res = 0;
if (!len)
len = strlen(str);
for ( ; len--; )
if (str[len] == c)
res++;
return res;
}
Obviously, the two functions do the same thing. Besides the fact that the first function is a little bit more readable than the second, is the second function more efficient since it avoids a local variable? I'm sure that these particular functions are really too simple to measure a true difference. I'm asking in more of a general or theoretical way.
Are there reasons why a user should avoid using input parameters as temporary storage (besides readability)? I'm not asking about pointers, where the input could be changed by the function. Does the compiler interpret the two functions differently which could cause function one to be preferred?
I searched through the questions, and I did find some related questions but none that I could find discussed the efficiency.
TL;DR
Write the code you find easiest to read/write/maintain. The difference between your functions will probably disappear when you compile with optimizations.
You might want to think about a couple of things that you can do to write a more flexible function, or at least: code that is easier to read. This answer will focus more on coding style, than the question Which is best, X or Y, because the answer will almost always be That depends on Z
Given that you're allowing the call to pass a 0 value for the string length, you could just write something like this:
int get_char_count(const char *str, char c)
{
int count = 0;
while(*str++) {
if (*str == c) {
++count;
}
}
return count;
}
That, to me, looks like the least amount of code, it's easy to read, and easy to maintain.
The drawbacks are:
Strings with '\0' characters in the middle (ie char[][]) can't be processed in full in a single call using this approach
Not possible to get the char count in a part of the string.
Strings containing '\0' chars can't be processed in full
If you want to support those use cases, you'll have to add a length argument. But even then, I'd just add it to the function, and not call strlen:
int get_char_count(const char *str, char c, unsigned int len)
{
int count = 0;
if (!len) {
while(*str++) {
if (*str == c) {
++count;
}
}
return count; // return early
}
//len is given
while (len--) {
if (str[len] == c) {
++count;
}
}
return count;
}
Now that I'm able to specify how many characters to iterate over, rather than to return on '\0', I can use this function, for example, to count how many occurrences of a given character are in an array of strings:
Example: count in char[][]
Example: cont in part of a string
Example: string with nul-chars
The first case (char [][]) works because of how the arrays are stored in memory: An array is a contiguous block of memory, and all values are stored in succession. If you know the total size of said block, you can use a char[][] as though it is one big string. The result being: only 1 function call is needed to count a character in all elements of the array.
The last case is pretty much the same thing, because the string in the example is actually how an array of strings is stored.
The second example (counting in partial string) is self-evident: rather than specifying the length of the full string, you can specify the number of characters you want to check...
The same approach can be used for strings lacking a terminating nul character
Because this is a fairly trivial function to implement, it's common to see most of the brackets being omitted:
while (*str++)
if (*str == c)
++count;
//or even
while(len--) count += str[len] == c;
The last version is technically valid, but it's not as easy to read. Omitting brackets for one-line if's and simple loops is fairly common, but has been the cause of bugs, like the goto fail bug from a few years back.
One last style-related thing:
When using the pointer to iterate over the string like I did in the first snippet, some will tell you that the best thing to do is to create a local pointer to increment:
int get_char_count(const char *str, char c)
{
int count = 0;
const char *local = str;
while(*local++) {
if (*local == c) {
++count;
}
}
return count;
}
The obvious advantage here being that you're not losing the original position/pointer that was passed in. If you later add something to the function, you can always reassign, or assign a new pointer based off str.

How to use getchar() function from a stored string array?

I wrote a simple C program in Linux that reads a single character from a string. I get some error regarding string functions. This is my code:
#include <stdio.h>
#include <string.h>
void main () {
char arr[10], vv[10];
int i = 0, len;
printf("enter the staement\n");
scanf("%s", arr);
len = strlen(arr);
printf("String laength=%d\n", len);
while ((vv[i] = getchar(arr)) != '\n') {
printf("%d charcter\n");
i++;
}
}
I don't want to use getchar() directly on the input text like this:
arr[i] = getchar();
I want to use getchar() from a stored string like this:
getchar(string array);
But unfortunately I get an error. Can I use the getchar() function directly from a stored string array?
Read about getchar. The link clearly says that getchar is a function that gets a character (an unsigned char) from stdin. Also, it takes no arguments. This would mean that you cannot copy each character of an array to another array using getchar. Just copy it directly using
while( (vv[i] = arr[i]) != '\n')
But I don't think this loop will end as scanf does not include the newline character when scanning a string(%s). So,you got two options:
Use fgets to get input.
Use the following
while( (vv[i] = arr[i]) != '\0')
When you have string in C, it is actually an array of chars which is terminated by '\0'. You do not need any method to get chars from it. Simply get the char as if you were accessing an array.
while((vv[i] = arr[i])!='\n')
As you have you arr[10] it will cause issues when your input is larger than 10 characters including the '\0'. So it is be better to declare it with enough space!
vv is a single char. You may not write vv[i].
Also, are you sure you want \n and not \0 [null]? scanf() won't give you a string with \n in it.
EDIT:
It is still unclear what you want to achieve, but if you want to check the presence of valid characters in the arr or vv, you can
take the base address of the arr or vv into a char *p.
check if (*p++) and do something.
EDIT:
You may try out something like
char * ip = NULL;
char * op = NULL;
int i = 10; //same as array size.
ip = arr;
op = vv;
while( (*op++ = *ip++) && i--)
{
//do something
};

Delete a char in string?

I tried searching for it on google and could not find a simple answer, most of the questions were asking to delete all occurrences of that char from the string and what not.
My pseudo code:
for (e=0;e<length of string;e++){
if (string[e] is not a number/alphabet){
#delete it
}
}
Is there a simple built in way of doing this?
Also another question, I need to do if not isalnum(string[e]), how would I go about doing so?
is it if !(isalnum(string[e])) or is it if (isalnum(string[e]))!=0?
Typically you would build up a second array and copy the valid symbols to that one.
Deleting numbers inside arrays is only possible if you move all trailing numbers down one step, which is very inefficient. If you need a container class where you can easily delete and add items in the middle, you should be using a linked list.
You can treat the return value of isalnum as bool type. Thus either
if ( !isalnum(string[e]) )
or
if ( isalnum(string[e]) !=0 )
are fine and completely equivalent.
You can filter out characters from a string in-place by keeping two indices. That works, because the string can only get shorter and the new string will fit into the old memory. Here's how with two pointers:
int str_alnum(char *str)
{
char *p, *q;
p = q = str;
while (*p) {
if (isalnum(*p)) *q++ = *p;
p++;
}
*q = '\0';
return q - str;
}
p walks the original string, q walks the new string, possibly trailing after p. q - str is the length of the new string, which might be handy as return value.
Note that you have to pass a string that can be modified, i.e. a char array, not a constant string literal.
This is one way to do it if you are using ASCII formatted characters.
char a[256]; // Some string
char destination[256];
char * pos = destination;
for(unigned int i=0;i>strlen(a)-1;++i)
{
if(((a[i]>='A'&& a[i]<='Z') || (a[i]>='a'&& a[i]<='z') || (a[i]>='1'&& a[i]<='9')))
*pos = a[i]; //replaces letter with a whitespace
++pos;
}
*pos = '\0';
Basically what it does it it converts the letter to the corrosponding intenger and then it checks its within the range that represents the letters between A-Z, a-z and 1-9.

Convert first character to capital upper case and count number of words in string in C programming

I am a beginner in C programming and need help! If given the following string as an example:
char prose[ ] = "Ping! King Alfred opened the oven door
To reveal nine perfect cakes.
Oh, what a difference to history
A kitchen timer makes."
How do I write a program that contains a function Cap(&prose[0]) that will convert the first character of each word to a upper case letter?
How do I write a program that contains function int count(&prose[0]) that counts the number of words in the above prose array?
Like all things in computer science, you're given a (relatively) large problem to solve, and the solution requires you to break it into smaller problems until each is solvable... then you do that. Here, you've got two problems (assign upper case at the beginning of each word, and count words) but they're closely related, reducing your work.
Your primary problem is to identify where a word starts (and, naturally, ends); once you can do that, your problems are mostly trivial.
You can probably (within the boundary of your problem) assume that the prose string starts with a word, so you've now only got to identify where words end/resume.
If you #include <ctype.h> you have some help: isalpha(c) indicates if a character (technically an int, but realistically a character) is alphabetic. There are many other character classification functions in there but isalpha() may be all you need.
I assume you know how to iterate through your prose string, but in case you dont:
char *p = prose;
while (*p != '\0') {
...
++p;
}
that's one (of many) ways; as you go through that loop, p will point to the next character. I.e., *p will be the next character.
Now, going through the string, you can use isalpha(*p) to detect if you're looking at an alhpabetic character or not. Combined with whatever you looked at the previous time through the loop, you can decide if you're at a word break... of this isalpha() and the previous one are the same, you've either just started a new word or just ended a word. If you're just starting a word, you can increase your word count and also capitalize this word (by changing the character, such as with *p = toupper(*p); (the toupper() function is also declared in <ctype.h>)
#include <stdio.h>
#include <ctype.h>
void Cap(char *string);
int count(char *string);
int main(void){
char prose[ ] =
"Ping! King Alfred opened the oven door\n"
"To reveal nine perfect cakes.\n"
"Oh, what a difference to history\n"
"A kitchen timer makes.";
printf("before:\n%s\n", prose);
Cap(&prose[0]);
printf("after:\n%s\n", prose);
printf("count of word : %d\n", count(&prose[0]));
return 0;
}
char *NextWordTop(char *string){
static char *p = NULL;
char *ret;
if(string)
p = string;
else if(!p)
return NULL;
while(isspace(*p))++p;
if(*p){
ret = p;
while(!isspace(*p))++p;
} else
ret = p = NULL;
return ret;
}
void Cap(char *str){
char *p;
for(p=NextWordTop(str); p ; p=NextWordTop(NULL))
*p = toupper(*p);
}
int count(char *str){
int c = 0;
char *p;
for(p=NextWordTop(str); p ; p=NextWordTop(NULL))
++c;
return c;
}

Resources