How to scan a string for specific terms - c

I'm trying to scan user input text for specific words and then, when those words occur, print them to the console.
#import <Foundation/Foundation.h>
#include <stdio.h>
int main(){
char cArray[] = "example";
char cInput[] = "";
char cOutput[] = "";
printf("\nType your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, 120, stdin);
}
printf("\nInitialised character array:\n");
for (int x=0; x<1; x++){
if(strncmp(&cInput[x], &cArray[x], 120) == 0){
strncpy(cOutput, cArray, strnlen(cInput, +1));
printf("%s\n", cOutput);
break;
}
}
}
Output:
Type your message:
example
Initialised character array:
Program ended with exit code: 120
Appreciate any feedback as I'm still learning :)
Thanks.
The edited code:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char *cArray[MAX_STR_LEN] = {"example", "this"};
char cInput[MAX_STR_LEN] = "";
char cOutput[MAX_STR_LEN] = "";
printf("Type your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, MAX_STR_LEN, stdin);
char * ptr = cInput;
while((ptr=strstr(ptr, *cArray)) != NULL){
strncpy(cOutput, ptr, strlen(*cArray));
printf("Initialised string array:\n%s\n", cOutput);
ptr++;
}
}
}
Works although I'm encountering a different problem now. The output only seems to register one word before it completes, thus only "example" is printed.
Output:
Type your message:
this is an example
Initialised string array:
example
Program ended with exit code: 0

char cInput[] = "";
The sizeof this array is 1.
fgets(cInput, 120, stdin);
This is array out of bound write which will lead to undefined behavior.
Have
char cInput[120] = "";
You need to take care of
char cOutput[120] = "";
also. Since you are trying to write to this array after comparing.

You need strstr function from string.h
const char * strstr ( const char * str1, const char * str2 );
the following gives you an example of usage:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char cArray[MAX_STR_LEN] = "example"; // string to be searched in the input string
char cInput[MAX_STR_LEN] = ""; // input string
char cOutput[MAX_STR_LEN] = ""; // buffer for found string
printf("\nType your message:\n");
for (int y=0; y<1; y++){ // this loop from original example looks strange, but it works
fgets(cInput, MAX_STR_LEN, stdin);
}
// search in the input string
char * ptr;
if( ( ptr=strstr(cInput, cArray) ) != NULL)
{
//copy the string to cOutput
strncpy(cOutput, ptr, strlen(cArray));
// output the found string
printf("String that was found: \n%s\n", cOutput);
}
else
{
printf("String was not found in the input!\n");
}
}
EDIT:
If you want to all the strings, use the following loop instead of if-else:
// search in the input string
char * ptr = cInput;
while( ( ptr=strstr(ptr, cArray) ) != NULL)
{
//copy the string to cOutput
strncpy(cOutput, ptr, strlen(cArray));
// output the found string
printf("String \"%s\" was found at position %d\n", cOutput, (int)(ptr - cInput + 1));
// find next string
ptr++;
}

Related

How to change one string to another with different sizes

I have a task to do. I have to work with strings. I will show you the input and output, because I think that will be clear what the task is.
Input: "aaa bbuvvvvo"
Output: "a$3 b$2uv$4o"
If there is the same symbols, I have to leave that symbol and then put dollar sign '$' and an integer of how many same signs was there. I am stuck on the spot, where I have to change string without losing any information.
I will leave my code here, it might help.
#include <stdio.h>
#include <string.h>
#define CAPACITY 255
#define MAX_NUMBER 10
void Output(char readFile[], char outputFile[], char string[]);
void changeString(char string[], char newString[]);
int main() {
char readFile[CAPACITY];
char outputFile[CAPACITY];
char string[CAPACITY];
// Input file's name
printf("Iveskite teksto failo varda: ");
scanf("%s", &readFile);
// Output file's name
printf("Iveskite teksto faila i kuri bus isvedamas atsakymas: ");
scanf("%s", &outputFile);
Output(readFile, outputFile, string);
return 0;
}
// Scanning file
void Output(char readFile[], char outputFile[], char string[])
{
char newString[CAPACITY];
FILE *input, *output;
input = fopen(readFile, "r");
while(fscanf(input, "%s", string) != EOF)
{
changeString(string, newString);
printf("%s\n", newString);
}
}
// Changing string to wanted string
void changeString(char string[], char newString[])
{
char number[MAX_NUMBER];
int symbols = 0;
int j;
for(int i = 0; string[i] != '\0'; ++i)
{
int temp = i;
newString[i] = string[i];
if(newString[i] == string[i + 1])
{
j = i;
while(string[j] == string[i])
{
++symbols;
++j;
}
// Changing int to char
sprintf(number, "%d", symbols);
newString[i + 1] = '$';
i += 2;
newString[i] = number[0];
symbols = 0;
}
}
}
I have tried to do that with function called changeString, but I get the wrong output all the time. Also the input I am getting is from .txt file.
EDIT: When I compiling this program right now, I get a$3 b$2v$4vo that output.
For starters this declaration in main
char string[CAPACITY];
does not make sense.
You should declare variables in scopes where they are used.
The variable string is used in the function Output where it is should be declared.
The function changeString should be declared like
void changeString( const char string[], char newString[]);
because the source string is not changed within the function.
Your function has several bugs.
For example it does not build a string in the array newString because it does not append the stored sequence in the array with the terminating zero character '\0'.
Secondly this increasing of the variable i
i += 2;
in general is invalid. You need to add to the variable i the number of repeated characters in the source string.
Or the number of repeated characters change greater than or equal to 10. In this case this statement
newString[i] = number[0];
will not produce correct result.
The function can be defined the following way as shown in the demonstration program below.
#include <stdio.h>
#define CAPACITY 255
void changeString( const char string[], char newString[] )
{
while ( *string )
{
*newString++ = *string;
size_t n = 1;
while (*++string == *( newString - 1 ) ) ++n;
if (n != 1)
{
*newString++ = '$';
int count = sprintf( newString, "%zu", n );
newString += count;
}
}
*newString = '\0';
}
int main( void )
{
char string[CAPACITY] = "aaa bbuvvvvo";
char newString[CAPACITY];
changeString( string, newString );
puts( newString );
}
The program output is
a$3 b$2uv$4o

C program that replace word in sentence to another word

I tried to replace a target word in sentence to another word but it doesn't work. Can you please help me with where I got wrong? It has a problem with strstr and strncopy. It says that *swap can be zero, which then makes strncpy stop. I tried to find way to solve this problem, but I couldn't. How can I fix this code?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *swap (char* data, const char* original, const char* change);
int main() {
char string[100];
char original[100];
char change[100];
printf("Input String : ");
fgets(string, 100, stdin);
printf("Find String : ");
fgets(original, 100, stdin);
printf("Replace String : ");
fgets(change, 100, stdin);
printf("%s", swap(string, change, original));
return 0;
}
char *swap(char* data, const char* original, const char* change) {
char* swap;
swap = strstr(data, original);
int num = strlen(change);
if (num == 0 || swap==0) return 0;
strncpy(swap, change, strlen(change));
printf("Result : %s", data);
return 0;
}
I have fixed your code and added a few tests to avoid buffer overflow vulnerability in your swap function.
My version take car of change and original being of different lengths.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *swap(char* data, int size, const char* original, const char* change);
int main()
{
char string[100];
char original[100];
char change[100];
printf("Input String : ");
fgets(string, sizeof(string), stdin);
string[strcspn(string, "\r\n")] = 0; // Remove EOL
printf("Find String : ");
fgets(original, sizeof(original), stdin);
original[strcspn(original, "\r\n")] = 0; // Remove EOL
printf("Replace String : ");
fgets(change, sizeof(change), stdin);
change[strcspn(change, "\r\n")] = 0; // Remove EOL
printf("%s\n", swap(string, sizeof(string), original, change));
return 0;
}
char *swap(char* data, int size, const char* original, const char* change)
{
if ((data == NULL) || (original == NULL) || (change == NULL))
return data; // Unspecified data
int datLen = strlen(data);
int oriLen = strlen(original);
if (oriLen == 0)
return data; // No original specified
char *swap = strstr(data, original);
if (swap == NULL)
return data; // Original not found in data
int chgLen = strlen(change);
if (size < (datLen + chgLen - oriLen))
return data; // Not enough space to store result
if (chgLen != oriLen)
memmove(swap + chgLen, swap + oriLen, 1 + datLen + oriLen - (swap - data));
memmove(swap, change, chgLen);
return data;
}
I have not changed that, but I think it is better to have swap return 0 or 1 if the swap took place or not. Returning data is not very useful as the swap is done in place.

First occurrence return with strstr function

Following on from my previous question, it now appears that my code only outputs the first occurrence of cArray from cInput. Is there a way to get strstr to return all of the occurrences instead of stopping the program at the first? Much appreciated.
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char *cArray[MAX_STR_LEN] = {"example", "this"};
char cInput[MAX_STR_LEN] = "";
char cOutput[MAX_STR_LEN] = "";
printf("Type your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, MAX_STR_LEN, stdin);
char * ptr = cInput;
while((ptr=strstr(ptr, *cArray)) != NULL){
strncpy(cOutput, ptr, strlen(*cArray));
printf("Initialised string array:\n%s\n", cOutput);
ptr++;
}
}
}
Output:
Type your message:
this is an example
Initialised string array:
example
Program ended with exit code: 0
Edited code:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main() {
char *cArray[MAX_STR_LEN] = { "example", "this", "is", "an" };
char cInput[MAX_STR_LEN] = { 0 };
int y = 0;
printf("Type your message:\n");
fgets(cInput, MAX_STR_LEN, stdin);
cInput[strlen(cInput) - 1] = 0; /* strip newline from input */
printf("\nInitialised string array:\n");
while (cArray[y])
{
char * ptr = cInput;
while ((ptr = strstr(ptr, cArray[y])) != NULL)
{
char *ep = strchr (ptr, ' ');
if (ep) *ep = 0; /* null-terminate at space */
printf("%s\n", ptr++);
if (ep) *ep = ' '; /* put the space back */
}
y++;
}
return 0;
}
New output:
Type your message:
this is an example
Initialised string array:
example
this
is
is
an
Program ended with exit code: 0
here is the corrected program:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char *cArray[MAX_STR_LEN] = { "example", "this" };
char cInput[MAX_STR_LEN] = "";
char cOutput[MAX_STR_LEN] = "";
printf("Type your message:\n");
fgets(cInput, MAX_STR_LEN, stdin);
printf("Initialised string array:\n");
for (int y = 0; y <= 1; y++){
char * ptr = cInput;
while ((ptr = strstr(ptr, cArray[y])) != NULL){
strncpy(cOutput, ptr, strlen(cArray[y]));
printf("[%d] - %s\n", y, cOutput);
memset(cOutput, 0, sizeof(cOutput));
ptr++;
}
}
getchar();
return 0;
}
Changes:
Used memset to reset the cOutput array so that during comparison
in the next iteration, it was empty.
Used the index y to keep track of each word from the array
Chagned array range from y<1 to y<=1
In addition to the other answers, here is a variation that eliminates intermediate variables and rearranges the loop logic slightly. There are many ways to approach the issue of returning all occurrences of strstr matches, so you have flexibility to use any manner that fits your needs:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main() {
char *cArray[MAX_STR_LEN] = { "example", "this" };
char cInput[MAX_STR_LEN] = { 0 };
int y = 0;
printf("Type your message:\n");
fgets(cInput, MAX_STR_LEN, stdin);
cInput[strlen(cInput) - 1] = 0; /* strip newline from input */
while (cArray[y])
{
char * ptr = cInput;
while ((ptr = strstr(ptr, cArray[y])) != NULL)
printf("\nInitialised string array:\n%s\n", ptr++);
y++;
}
return 0;
}
output:
alchemy:~/dev/src-c/tmp> ./bin/strstrmulti
Type your message:
my example of this example for fun
Initialised string array:
example of this example for fun
Initialised string array:
example for fun
Initialised string array:
this example for fun
To isolate only the word matching in cArray, you can use strchr to test if a space remains in the input string following the pointer returned the strstr. If so, just null-terminate the string where the next space appears which will isolate just the searched for word. If I misunderstood the comment, just leave another, I'm happy to help. (code changes only)
while (cArray[y])
{
char * ptr = cInput;
while ((ptr = strstr(ptr, cArray[y])) != NULL)
{
char *ep = strchr (ptr, ' ');
if (ep) *ep = 0; /* null-terminate at space */
printf("\nInitialised string array:\n%s\n", ptr++);
if (ep) *ep = ' '; /* put the space back */
}
y++;
}
isolated output:
alchemy:~/dev/src-c/tmp> ./bin/strstrmulti
Type your message:
my example of this example for fun
Initialised string array:
example
Initialised string array:
example
Initialised string array:
this
Here is a bit of code to look at whole words only using the inch-worm method. I haven't had a lot of time to look at all potential gotchas, but this should get you going. Just replace the code in your last version:
while (cArray[y])
{
char *ptr = cInput;
char *ep = NULL;
while ((ep = strchr (ptr, ' '))) /* set end-pointer to each space in input */
{
*ep = 0; /* null-terminate and compare word */
if (strcmp (ptr, cArray[y]) == 0)
printf("\nInitialised string array:\n%s\n", ptr);
*ep = ' '; /* restore space in string */
ptr = ++ep; /* set pointer to next char after space */
}
if (strcmp (ptr, cArray[y]) == 0) /* compare last word in input */
printf("\nInitialised string array:\n%s\n", ptr);
y++;
}
output w/updated cArray
alchemy:~/dev/src-c/tmp> ./bin/strstrmulti
Type your message:
this is an example to test the example for fun
Initialised string array:
example
Initialised string array:
example
Initialised string array:
this
Initialised string array:
is
Initialised string array:
an

Save hex value from input text to a string var and vice versa ANSI C

I need to save the hex of a text to a string:
_____________________
Input: apple
Output: 6170706c65
_____________________
char * text = "apple";
char * hextext = convertToHex(text); // -> ?! I don't know how
printf("Hextext is %s\n", hextext); // -> Hextext is 6170706c65
and
char * hextext = 6170706c65;
char * text = convertToText(hextext);
printf("Text is %s\n", text);
Using Printf, its easy using %hx, but I need the values on the variables!
Can anybody help, please?!
Thanks.
My final code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void convertToHex(char* input, char** output)
{
char* ptr;
int i;
// Allocate memory for hex string
*output = malloc(2 * strlen(input) + 1);
// Initialize pointer to start of the output buffer
ptr = *output;
// Read each char in input. Use sprintf to append the 2 char hex value.
// Finally advance the pointer 2 places in the output buffer.
for(i=0; i<strlen(input); i++)
{
sprintf(ptr, "%x", input[i]);
ptr++; ptr++;
}
}
void convertHexToString(char* input, char** output)
{
char* ptr;
int c;
// Allocate memory for hex string
*output = malloc(2 * (strlen(input)/2)%2==0 ? (strlen(input)/2) + 1 : (strlen(input)/2));
// Initialize pointer to start of the output buffer
ptr = *output;
// Read two char in input. Use sprintf to append the char value.
// Finally advance the input place in the output buffer.
for (;input[0] && input[1] && sscanf(input, "%2x", &c); input += 2)
{
sprintf(ptr, "%c", c);
ptr++;
}
}
int main(void)
{
char* text = "apple";
char* hexkey;
char* strtext;
convertToHex(text, &hexkey);
printf("Input: %s\n", text);
printf("Output: %s\n", hexkey);
convertHexToString(hexkey, &strtext);
printf("\nInput2: %s\n", hexkey);
printf("Output2: %s\n", strtext);
free(hexkey);
free(strtext);
return 0;
}
Special thanks to Erik Nedwidek for help!
Here's what I was referring to:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void convertToHex(char* input, char** output) {
char* ptr;
int i;
// Allocate memory for hex string
*output = malloc(2 * strlen(input) + 1);
// Initialize pointer to start of the output buffer
ptr = *output;
// Read each char in input. Use sprintf to append the 2 char hex value.
// Finally advance the pointer 2 places in the output buffer.
for(i=0; i<strlen(input); i++) {
sprintf(ptr, "%x", input[i]);
ptr++; ptr++;
}
}
int main(void) {
char* text = "apple";
char* hex;
convertToHex(text, &hex);
printf("Input: %s\n", text);
printf("Output: %s\n", hex);
free(hex);
return 0;
}
The output is:
Input: apple
Output: 6170706c65

How to assign char * to character array?

I have following code:
int main(){
char sentence[] = "my name is john";
int i=0;
char ch[50];
for (char* word = strtok(sentence," "); word != NULL; word = strtok(NULL, " "))
{
// put word into array
// *ch=word;
ch[i]=word;
printf("%s \n",ch[i]);
i++;
//Above commeted part does not work, how to put word into character array ch
}
return 0;
}
I am getting error: error: invalid conversion from ‘char*’ to ‘char’ [-fpermissive]
I want to store each word into array, can someone help?
To store a whole set of words you need an array of words, or at least an array of pointers pointing to a word each.
The OP's ch is an array of characters and not an array of pointers to characters.
A possible approach would be:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define WORDS_MAX (50)
int main(void)
{
int result = EXIT_SUCCESS;
char sentence[] = "my name is john";
char * ch[WORDS_MAX] = {0}; /* This stores references to 50 words. */
char * word = strtok(sentence, " "); /* Using the while construct,
keeps the program from running
into undefined behaviour (most
probably crashing) in case the
first call to strtok() would
return NULL. */
size_t i = 0;
while ((NULL != word) && (WORDS_MAX > i))
{
ch[i] = strdup(word); /* Creates a copy of the word found and stores
it's address in ch[i]. This copy should
be free()ed if not used any more. */
if (NULL == ch[i])
{
perror("strdup() failed");
result = EXIT_FAILURE;
break;
}
printf("%s\n", ch[i]);
i++;
word = strtok(NULL, " ")
}
return result;
}

Resources