How many this word in the array string - arrays

I want to count how many this word and operator in the string but I try to use strchr and it doesn't work.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
int x,count =0;
char buff[100]="1+2.3(7^8)sin cos + cos sin_e-2x+x2*2!/_x1 sine";
//gets(buff);
strupr(buff);
for (int i = 0; buff[i] != '\0'; i++)
{
if (buff[i] == '+' || buff[i] == '-' || buff[i] == '*' ||
buff[i] == '/' || buff[i] == '^'|| buff[i] == '(')
{
count++;
}
}
char *op2;
int check=0;
char cpysin[100],cpycos[100];
strcpy(cpysin,buff);
strcpy(cpycos,buff);
do
{
if(strchr(cpysin,'SIN')!=0)
{
count++;
strcpy(cpysin,strstr(cpysin,"SIN"));
cpysin[0] = ' ';
cpysin[1] = ' ';
cpysin[2] = ' ';
}
else
{
break;
}
}
while(check==0);
do
{
if(strchr(cpycos,'COS')!=0)
{
count++;
strcpy(cpycos,strstr(cpycos,"COS"));
cpycos[0] = ' ';
cpycos[1] = ' ';
cpycos[2] = ' ';
}
else
{
break;
}
}
while(check==0);
printf("FINAL \n%d",count);
}
I only work when I do it in the loop while trying to find how many sins are in there but it doesn't work when I put cos function on it. Please tell me how to fix this and what if I need to write more functions to find.

strchr(cpysin, 'SIN') is wrong.
Unfortunately the compiler may not give you a warning because 'SIN' can be interpreted as 4 byte integer. The second parameter is supposed to be an integer, but strchr really wants character, it chops it off to 'N'
Just remember that in C you work with single characters 'a' or strings "cos" (or you can come accross wide characters/strings)
Use strstr to find a string. For example, to find "cos":
char* ptr = buff;
char* find = strstr(ptr, "cos");
"1+2.3(7^8)sin cos + cos sin_e-2x+x2*2!/_x1 sine";
---------------^ <- find
find will point to "cos + cos sin_e-2x+x2*2!/_x1 sine"
You can increment ptr and look for the next occurrence of "cos".
Also note, you can declare char buff[] = "...", you don't have to assign the buffer size.
char buff[] = "1+2.3(7^8)sin cos + cos sin_e-2x+x2*2!/_x1 sine";
int count = 0;
const char* ptr = buff;
const char* text = "cos";
//must terminate when ptr reaches '\0' which is at the end of buff
//there is serious problem if we read past it
while(*ptr != '\0')
{
char* find = strstr(ptr, text);
if (find != NULL)
{
printf("update [%s]\n", find);
count++;
ptr = find + strlen(text);
//next search starts after
}
else
{
ptr++;
//next character start at next character
}
}
printf("%s count: %d\n", text, count);

Related

Why do the values in my dynamically-allocated memory look like they're being overwritten

I'm working on an assignment that is supposed to parse a string into separate tokens without the use of the c string library and while dynamically allocating any necessary memory. I thought I had everything working correctly, except now it looks like every value is being overwritten every time I write a new value.
Here's my code. Sorry it's a mess, I've been in a hurry and reluctantly have been working with functions I don't fully understand. The problem is probably something dumb, but I'm out of time and it's clear I probably wont be able to figure it out myself.
int makearg(char s[], char **args[]);
int main() { char **tokenArray; char strInput[MAXSTRING]; int tokenResult; int i = 0;
printf("Input String to be Parsed: "); scanf("%[^\n]%*c", strInput);
tokenResult = makearg(strInput, &tokenArray);
printf("argc: %d\n", tokenResult); for (i = 0; i < tokenResult; i++) {
printf("arg(%d): %s\n", i, tokenArray[i]); } }
int makearg(char s[], char **args[]) { int numTokens = 0; int lastSpace = 0; int i; int fakeI; char token[MAXSTRING]; int subFromPos = 0; int firstToken = 1;
*args = NULL; while ((s[i] != '\n') && (s[i] != '\0') && (s[i] != '\r')) {
fakeI = i;
if ((s[i + 1] == '\n') || (s[i + 1] == '\0'))
{
fakeI = i + 1;
}
token[i - lastSpace - subFromPos] = s[i];
if ((s[fakeI] == ' ') || (s[fakeI] == '\n') || (s[fakeI] == '\0') || (s[fakeI] == '\r'))
{
if (firstToken == 1)
{
token[fakeI - lastSpace] = '\0';
firstToken = 0;
} else if (firstToken == 0){
token[i - lastSpace] = '\0';
printf("Saved Token 1: %s\n", *args[numTokens - 1]); //test to see if the token got written properly
if (numTokens > 1){
printf("Prior Saved Token: %s\n", *args[numTokens - 2]); //test to see if the tokens are overwritten
}
if (numTokens > 2){
printf("Prior Saved Token 2: %s\n", *args[numTokens - 3]); //test to see if the tokens are overwritten
}
}
*args = realloc(*args, (numTokens + 1));
args[numTokens] = NULL;
args[numTokens] = realloc(args[numTokens], (fakeI - lastSpace + 1));
*args[numTokens] = token;
printf("Saved Token: %s\n", *args[numTokens]); //test to see if the token got written properly
numTokens++;
lastSpace = fakeI;
subFromPos = 1;
}
i++; } numTokens++; return numTokens; }
For whatever reason Saved Token, Saved Token 1, Prior Saved Token, and Prior Saved Token 2 all print the same value every time they run (by which I mean if one of them prints the word "hello", they all print the word hello. That seems to tell me that the previous data is being overwritten.
Additionally, the for-loop in the main function is supposed to go through and print every value in the array, but instead it's only printing the following (in this scenario I was testing with the string "hello my one true friend":
arg(0): friend
arg(1): (null)
arg(2): (null)
What am I doing wrong here? I'm sure it's something dumb that I'm overlooking, but I just can't find it. Am I writing in the data incorrectly? Is it actually not being overwritten and just being printed incorrectly. At this point any advice at all would be greatly appreciated.
Ok well my dev env picked up immediatly
int i; <<<<=====
int fakeI;
char token[255];
int subFromPos = 0;
int firstToken = 1;
*args = NULL;
while ((s[i] != '\n') && (s[i] != '\0') && (s[i] != '\r')) { <<<<<=
gave
C4700 uninitialized local variable 'i' used
after that all bets are off

palindrome c program is not working for some reason

this program checks weather the entered string is palindrome or not . it should be in a way like it should even tell the string is palindrome if there is space or any special character
like messi is a palindrome of iss em
and ronald!o is a palindrome of odlanor
this is the program and for some odd reason it is strucking and not working
#include <stdio.h>
#include <string.h>
int main() {
char palstr[100], ans[100];
printf("enter the string for checking weather the string is a palindrome or not");
scanf("%[^/n]", &palstr);
int ispalin = 1, i = 0, n = 0;
int num = strlen(palstr);
printf("the total length of the string is %d", num);
while (i <= num) {
if (palstr[i] == ' ' || palstr[i] == ',' || palstr[i] == '.' ||
palstr[i] == '!' || palstr[i] == '?') {
i++;
}
palstr[n++] == palstr[i++];
}
int j = num;
i = 0;
while (i <= num) {
ans[j--] = palstr[i];
}
printf("the reverse of the string %s is %s", palstr, ans);
if (ans == palstr)
printf("the string is a palindrome");
else
printf("the string is not a palindrome");
return 0;
}
A few points to consider. First, regarding the code:
if (ans == palstr)
This is not how you compare strings in C, it compares the addresses of the strings, which are always different in this case.
The correct way to compare strings is:
if (strcmp(ans, palstr) == 0)
Second, you should work out the length of the string after you have removed all unwanted characters since that's the length you'll be working with. By that I mean something like:
char *src = palstr, dst = palstr;
while (*src != '\0') {
if (*c != ' ' && *src != ',' && *src != '.' && *src != '!' && *src != '?') {
*dst++ = *src;
}
src++;
}
Third, you have a bug in your while loop anyway in that, if you get two consecutive bad characters, you will only remove the first (since your if does that then blindly copies the next character regardless).
Fourth, you may want to consider just stripping out all non-alpha characters rather than that small selection:
#include <ctype.h>
if (! isalpha(*src) {
*dst++ = *src;
}
Fifth and finally, you don't really need to create a new string to check for a palindrome (though you may still need to if you want to print the string in reverse), you can just start at both ends and move inward, something like:
char *left = &palstr, right = palstr + strlen(palstr) - 1, ispalin = 1;
while (left < right) {
if (*left++ != *right--) {
ispalin = 0;
break;
}
}
There may be other things I've missed but that should be enough to start on.
well, the are so many bugs in this code. I will point them out with comments.
#include <stdio.h>
#include <string.h>
int main() {
char palstr[100], ans[100];
printf("enter the string for checking weather the string is a palindrome or not\n");
scanf("%s", palstr); // your former code won't stop input util Ctrl+D
int ispalin = 1, i = 0, n = 0;
int num = strlen(palstr);
printf("the total length of the string is %d\n", num);
while (i < num) { // < insted of <=
if (palstr[i] == ' ' || palstr[i] == ',' || palstr[i] == '.' ||
palstr[i] == '!' || palstr[i] == '?') {
i++;
continue;// without this, marks still in the string
}
palstr[n++] = palstr[i++]; //should be =
}
palstr[n] = '\0'; //
num = n; // the length might be changed
i = 0;
int j = num-1; // reverse
while (i < num) { //
ans[i++] = palstr[j--]; //
}
ans[i] = '\0'; //
printf("the reverse of the string %s is %s\n", palstr, ans);
//if (ans == palstr) they can never be equal
if (strcmp(ans, palstr)==0)
printf("the string is a palindrome\n");
else
printf("the string is not a palindrome\n");
return 0;
}

seperate the word from a sentence without library function

Here i wrote a code to separate the words from a given sentence without using strtok() function.But the problem is it only prints the first word.Why rest of the words don't get printed ?
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This, a sample string.";
int i=0,k,begin,end;
while(str[i]!='\0'){
while(str[i]==' '){
i++;
}
begin = i;
while(str[i]!=' ' && str[i]!='\0'){
i++;
}
end = i-1;
char *ptr =(char *)malloc((end-begin)*sizeof(char));
for(k=begin;k<=end;k++){
ptr[k] = str[k];
}
printf("%s\n",ptr);
if(str[i]=='\0'){
break;
}
}
}
The complete code should be like this.
I have changed code on top of your code.
int main ()
{
char str[] ="This, a sample string.";
int i=0,k,begin,end;
int t;
while(str[i]!='\0'){
begin = i;
while(str[i]!=' ' && str[i]!='\0'){
i++;
}
end = i-1;
char *ptr = (char *) malloc( (i-begin)*sizeof(char) + 1);
t=0;
for(k=begin;k<=end;k++){
ptr[t++] = str[k];
}
ptr[t] = '\0';
puts(ptr);
if(str[i]=='\0'){
break;
} else
while(str[i] == ' ') i++; //To avoid multiple spaces
}
return 0;
}
-Thanks
The problem with your code is here:
for(k=begin;k<=end;k++){
ptr[k] = str[k];
}
the k is being used as index variable for both ptr and str, what you should do is use a separate variable for ptr, so that it fills up characters from 0 index.
Also you are not allocating the correct amount of space. The number of characters are end - begin + 1 and you also have to allocate space for null character(string terminating character).
So correct allocation is:
char *ptr =(char *)malloc((end-begin+2)*sizeof(char));
and your correct code is:
int index = 0;
for(k = begin;k <= end; k++){
ptr[jj++] = str[k];
}
ptr[end - begin + 1] = '\0';
If you're allowed to modify the string in-place, you could do something like
#include <stdio.h>
static void print_words(char *str) {
char *start = str; // Word start pointer.
for(;*str;str++) { // While there are characters...
if(*str == ' ') { // Space found!
*str = '\0'; // Replace the space with a null to end the string
printf("%s\n", start); // Output the now null-delimited string
*str = ' '; // Return the string to its original form
start = str + 1; // Advance the word-start pointer
}
}
printf("%s\n", start); // Print the last word remaining unprinted, if any
}
int main()
{
char str[] = "This, a sample string.";
print_words(str);
}
You have missed some logics in your code.
you are traversing to second word by default. Which is not your requirement.
This block identifies word from given string.
You are allocation one byte less than we need.
One extra byte is required for termination string. null char.
**4. ptr[k] = str[k]
This is the hole in your code.
This should be like ptr[0] = str[k];**
you missed incrementing i value to iterate further.
==================point 1=======================
while(str[i]!='\0'){
while(str[i]==' '){ -> this is point no 1. This logic will skip first word
i++;
}
=================point 2 ================
begin = i;
while(str[i]!=' ' && str[i]!='\0'){
i++;
}
**end = i-1;**
==========================================
char *ptr =(char *)malloc((end-begin)*sizeof(char)); -> point 3.
point 4 :
for(k=begin;k<=end;k++){
ptr[k] = str[k];
}
printf("%s\n",ptr);
if(str[i]=='\0'){
break;
}
point 5 :
else
i++;
}
-Thanks
I have found the problem and come up with the solution :
1.First problem is i was not assigning the correct value to *ptr.so , i used a variable j to start from the beginning of current index
2.I needed to null terminate each capture
ptr[k]='\0';
3.So the changes i made overall is the following :
for(k=0,j=begin;k<=end-begin;k++,j++){ // use a variable j to start from the beginning of current index
ptr[k] = str[j];
}
ptr[k]='\0';
Full code:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This, an sample string.";
int i=0,j,k,begin,end;
char *ptr;
while(str[i]!='\0'){
while(str[i]==' '){
i++;
}
begin = i;
while(str[i]!=' ' && str[i]!='\0'){
i++;
}
end = i-1;
ptr =(char *)malloc((end-begin)*sizeof(char));
for(k=0,j=begin;k<=end-begin;k++,j++){ // use a variable j to start from the beginning of current index
ptr[k] = str[j];
}
ptr[k]='\0';
printf("%s\n",ptr);
if(str[i]=='\0'){
break;
}
}
}

Unexpected Behaviour when using strtok

So I'm given a string as such:
Hello6World66ABC
Where I'm told to replace single instances of the character '6' to be two asteric characters "**"
And multiple instances of 6's to be two of these characters "^^" (Any combinations of the number 6 in a row would qualify.
I'm attempting to do this by passing through each character in a char *,then if I find the 6 character, I check if the next character is a 6, if not we have the first case, otherwise we have the second case (Multiple 6's).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char * str;
int i;
str = malloc(17);
strcpy(str,"Hello6World66ABC");
for(i=0; i < strlen(str); i++) {
if(str[i] == '6') {
if(str[i+1] != '6') {
char * token = strtok(str,"6");
strcpy(str,token);
strcat(str,"**");
printf("String is now %s\n",str);
token = strtok(NULL,""); /*get the rest of the string*/ /* should be World66ABC */
printf("Rest of the string is %s\n",token);
str = (char *) realloc(str,strlen(str) + strlen(token) + 1);
strcat(str,token);
printf("String is now %s\n",str);
/* should be Hello**World66ABC */
}
else {
/*if the next characters are also (multiple ones in a row) 6's, replace it with two ^^ characters*/
char * token = strtok(str,"6");
token = strtok(NULL,"6");
printf("TOKEN IS %s\n",token);
strcpy(str,token);
strcat(str,"^^");
token = strtok(NULL,""); /*get the rest of the string*/ /* should be World66ABC */
printf("Rest of the string is %s\n",token);
str = (char *) realloc(str,strlen(str) + strlen(token) + 1);
strcat(str,token);
printf("String is now %s\n",str);
}
}
}
free(str);
return 0;
}
By the string given, My expected final string should be:
Hello**World^^ABC
However, my strtok calls don't work the way I intended.
In the second if statement, where I check if (str[i+1] != '6'), I'm checking if there is only a single 6, there is.
Then I call strtok and print everything before it:
it prints: Hello**
Which is correct
I strcat the new characters on to it which works, however, on my second strtok call, to get the rest of the string, it just doesn't work.
It instead prints:
"Rest of the string is *"
So clearly it's not getting the rest of the string, even though I set the delimiter to be an empty string.
I tried to change the delimiter to be other characters, but each result in the same output. I'm also reallocating because the string gets longer, in the first case. Also the else statement seems to never run, even though I clearly have a case where there are multiple 6's.
I'm not sure where I've gone wrong here, any ideas?
This is untested, but it shows the general idea.
strcpy(str,"Hello6World66ABC");
// New string will be at most 2x as long
char *new_str = calloc(strlen(str) * 2 + 1, 1);
int new_str_index = 0;
for (int i = 0; 0 != str[i]; i++) {
// Check for 6
if ('6' == str[i]) {
// Check for 2nd 6
if ('6' == str[i+1]) {
// Add chars
new_str[new_str_index++] = '^';
new_str[new_str_index++] = '^';
// Consume remaining 6s - double check this for off-by-one
while ('6' == str[i+1]) i += 1;
}
else {
// Add chars
new_str[new_str_index++] = '*';
new_str[new_str_index++] = '*';
}
}
// No 6s, just append text
else {
new_str[new_str_index++] = str[i];
}
}
OP asked for a simple way of altering the '6' characters in the string. If you want to write to another string instead of printing directly, I leave it to you to define the other (large enough) string, and copy the chars to that string instead of to stdout. But do NOT try to alter the string passed, it is doomed to fail.
#include <stdio.h>
void sixer(char *str)
{
int i = 0, sixes;
while(str[i] != '\0') {
if(str[i] == '6') {
sixes = 0;
while(str[i] == '6') {
sixes++;
i++;
}
if(sixes == 1) {
printf("**");
}
else {
printf("^^");
}
}
else {
printf("%c", str[i]);
i++;
}
}
printf("\n");
}
int main(void)
{
sixer("Hello6World66ABC");
sixer("6");
sixer("66666");
return 0;
}
Program output
Hello**World^^ABC
**
^^

Find spaces and alphanumeric characters in a string

I need to develop a function that goes through a character string and detects letters (lower and upper cases), digits 0-9 and spaces ' '. If the functions finds only valid characters (the characters listed before) it returns 1 otherwise(if the string has characters like !,&,/,£, etc.) it returns 0. I am aware of a function that finds characters and digits which is isalnum().That is not helpful to find spaces. Does anyone can provide inbuilt or manual function which can detect characters,digits and spaces all together.
I've developed mine as under but function does not detect invalid character !,&,/,£ etc. in middle of the string and therefore it does not return the value I expect.
for (i=0; i<strlen(str); i++) {
if ((str[i]>='A' && str[i]<='Z') || str[i] == ' ' || (str[i]>='a' && str[i]<='z') || (str[i]>='0' && str[i]<='9'))
for (i=0; i<strlen(str); i++) {
char *p = str;
while (*p) {
if (isalnum((unsigned char) *p) || *p == ' ') {
res =1;
} else {
res = 0;
}
p++;
}
}
You can make the code more succinct:
int Validate_Alphanumeric(char *str)
{
unsigned char *ptr = (unsigned char *)str;
unsigned char uc;
while ((uc = *ptr++) != '\0')
{
if (!isalnum(uc) && uc != ' ')
return 0;
}
return 1;
}
Amongst other things, this avoids reevaluating strlen(str) on each iteration of the loop; that nominally makes the algorithm quadratic as strlen() is an O(N) operation and you would do it N times, for O(N2) in total. Either cache the result of strlen(str) in a variable or don't use it at all. Using strlen(str) requires the entire string to be scanned; the code above will stop at the first punctuation or other verboten character without scanning the whole string (but the worst case performance, for valid strings, is O(N)).
I came up with a function that goes through the string and that is able to return 0 if an invalid character (ex. $&$&&(%$(=()/)&)/) is found.
int Validate_Alphanumeric (char str[]) {
int i;
int res;
int valid=0;
int invalid=0;
const char *p = str;
while (*p) {
if (isalnum((unsigned char) *p) || *p == ' ') {
valid++;
} else {
invalid++;
}
p++;
}
if (invalid==0)
res=1;
else
res=0;
return res;
}

Resources