Passing a scanf string from a function - c

It shows nothing when you pass the string to the function
int main(void){
char *string[200];
getChar(string);//starts function
printf("This is the string %s",*string);//prints
return 0;
}
Void getChar(char *String[200]){
scanf(" %s",String[200]);//gets string
}

There are multiple problems:
You should use an array of char instead of an array of char *,
you should pass the array directly to scanf():
Void has no capital: void
getChar is confusing to read a string and should be declared or defined before use.
the initial space in scanf(" %s", is redundant: %s already skips initial spaces.
you must tell scanf() the maximum number of characters to store into the destination array, otherwise you will have undefined behavior if the input has too many characters.
Here is a modified version:
#include <stdio.h>
int getword200(char *buf) {
return scanf("%199s", buf);
}
int main() {
char word[200];
if (getword200(word) == 1)
printf("This is the string: %s\n", word);
return 0;
}
The above function assumes the array has a length of at least 200. It would be more general to pass the actual array length and modify the code to handle any length:
#include <limits.h>
#include <stdio.h>
int getword(char *buf, size_t size) {
char format[32];
int length;
if (size == 0)
return NULL;
if (size == 1) {
*buf = '\0';
return buf;
}
if (size > INT_MAX)
length = INT_MAX;
else
length = size - 1;
snprintf(format, sizeof format, "%%%ds", length)
return scanf(format, buf);
}
int main() {
char word[200];
if (getword(word, sizeof word) == 1)
printf("This is the string: %s\n", word);
return 0;
}

Related

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.

Construct String in C

Here is the demo code I am using to construct string from char arrays, Is there any better way to construct String *RV200# *FV200# ??
int main()
{
char String4H1[10] = "*FV";
char String4H3[10] = "*RV";
char String4H2[10] = "#";
char data1[10];
char data2[10];
snprintf(data1,4, "%03d", 200); //Convert integer to string function
snprintf(data2,4, "%03d", 200); //Convert integer to string function
ConvertToString(String4H1,data1, 3); //*FV200
ConvertToString(String4H3,data2, 3); //*RV200
ConvertToString(String4H1,String4H2,6); //*FV200#
ConvertToString(String4H3,String4H2,6); //*RV200#
//Display String4H1 And String 4H3
}
void ConvertToString(char subject[], const char insert[], int pos)
{
char buf[100] = {};
strncpy(buf, subject, pos); // copy at most first pos characters
int len = strlen(buf);
strcpy(buf+len, insert); // copy all of insert[] at the end
len += strlen(insert); // increase the length by length of insert[]
strcpy(buf+len, subject+pos); // copy the rest
strcpy(subject, buf); // copy it back to subject
// deallocate buf[] here, if used malloc()
}
The number 200 is not known at the start of the program, it is fetched from memory using the IDE function to get value from particular memory address.
like this :-
unsigned short BUF = GetWord(#FrontVIB#,0);
unsigned short BUF1 = GetWord(#RearVIB#,0);
//BUF and BUF1 stores the value of address #FrontVIB# and #RearVIB# respectively
**structure** :-
unsigned short GetWord( #Address Alias#, Address Offset );
That's a simple example. Probably I'll be down-voted :)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
bool concatenateString(char **dest, size_t *size, char *stringToAdd)
{
bool retVal = true;
char *dest_old = *dest;
*size += strlen(stringToAdd);
if (*dest == NULL)
{
*size += 1; // to add null terminator of string
*dest = calloc(1, size);
}
else
{
*dest = realloc(*dest, size);
}
if (dest == NULL)
{
free(dest_old);
retVal = false;
}
else
{
strcat(*dest, stringToAdd);
}
return retVal;
}
int main()
{
char newString[32] = {0};
int number;
size_t size = 0;
char *data1 = NULL;
printf("Insert a string:");
scanf(" %s", newString);
if (concatenateString(&data1, &size, newString))
{
printf("Insert a number:");
scanf(" %d", &number);
sprintf(newString, "%03d", number);
if (concatenateString(&data1, &size, newString) )
{
printf("Insert a string:");
scanf(" %s", newString);
if (concatenateString(&data1, &size, newString))
printf("%s\n", data1);
}
}
free(data1);
}
Without using dynamic allocation
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
bool concatenateString(char *dest, size_t size_of_dest, char *stringToAdd)
{
bool retVal = true;
size_t new_size = strlen(dest) + strlen(stringToAdd);
if (new_size < size_of_dest)
{
strcat(dest, stringToAdd);
}
else
{
retVal = false;
}
return retVal;
}
int main()
{
char result[128] = {0};
char newString[32] = {0};
int number;
printf("Insert a string:");
scanf(" %s", newString);
printf("%s\n", newString);
if (concatenateString(result, sizeof(result), newString))
{
printf("Insert a number:");
scanf(" %d", &number);
sprintf(newString, "%03d", number);
if (concatenateString(result, sizeof(result), newString) )
{
printf("Insert a string:");
scanf(" %s", newString);
if (concatenateString(result, sizeof(result), newString))
printf("%s\n", result);
}
}
}
INPUT
Insert a string: *RV
Insert a number: 200
Insert a string: #
OUTPUT
*RV200#
A number of issues, I am only tackling ConvertToString()
Although some attempts made at coping with string buffer issues, too many holes exist in OP's code. Consider the following.
void ConvertToString(char subject[], const char insert[], int pos) {
char buf[100] = {};
strncpy(buf, subject, pos); // copy at most first pos characters
int len = strlen(buf);
...
What is the impact of pos == 100?
strlen(buf) may attempt to find the length of a character array with no null character --> UB.
What is the impact of pos > 100?
strncpy() attempts to write data outside the bonds of buf.
Pedantic: What is the impact of pos < 0?
strncpy() attempts to write data outside the bonds of buf as pos is converted into an excessive large unsigned number.
Concerning strcpy(buf+len, subject+pos);
What is the impact if pos exceeds strlen(subject)
UB as code attempts to read outside subject.
Re-write attempt. The key elements: include the size available for the expanded subject is passed in and determine string lengths. Then test for acceptability. After all that, shift the end of subject to make room for insert.
void ConvertToString(char subject[], size_t subject_size, const char *insert,
size_t pos) {
size_t insert_length = strlen(insert);
size_t subject_length = strlen(subject);
// Insure pos does not exceed subject_length,
// this critical part missing in OP code
if (pos > subject_length) {
pos = subject_length;
}
// Insure we have enough space
size_t buf_size = subject_length + insert_length + 1;
if (buf_size > subject_size) {
Handle_Insufficent_subject_size();
return;
}
// Move end portion of `subject` over to the right `insert_length` places.
memmove(subject + pos + insert_length, subject + pos, subject_length - pos + 1);
memcpy(subject + pos, insert, insert_length); // copy insert
}

Find string length using strlen and a function. print with empty string

So I am writing this code to print string length of any string I input and I basically have the code already working but I am having trouble because when I enter a blank string my program doesn't print to screen correctly. It works with a space(spacebar) and all other strings but I must be able to enter an empty string. we are supposed to use something like:
buf[strlen(buf) - 1] = '\0';
to enter and print empty strings,
but I am not sure how to enter it in the code correctly. Any ideas??
here is my program:
#include<stdio.h>
#include<conio.h>
#include<string.h>
int *MyStrlen(const char *string2);
int main()
{
char string2[100];
printf("Enter a string: \n");
scanf("%100[^\n]",&string2);
int length, length2;
length = strlen(string2);
length2 = MyStrlen(string2);
printf("strlen(''%s'') returned %d\n", &string2, length);
printf("MyStrlen(''%s'') returned %d\n", &string2, length2);
return 0;
}
also, here is MyStrlen function, All works correctly besides entering empty string.
int *MyStrlen(const char *string2)
{
int stringcount=0;
while (string2[stringcount]!='\0')
{
stringcount++;
}
return stringcount;
}
Maybe the problem could be corrected with:
Initilize the first element of string2 to '\0' before the scanf:
string2[0] = '\0';
Change the return type of int *MyStrlen(...) to int:
int MyStrlen(const char *string2);
As this post: How to input a string using scanf in c including whitespaces,
a safer way is to specify a size 1 less than the size of string2 buffer:
scanf("%99[^\r\n]", &string2[0]);
Check out the scanf man page for more information.
The code:
#include<stdio.h>
#include<conio.h>
#include<string.h>
int MyStrlen(const char *string2);
// change the return type to int
int MyStrlen(const char *string2)
{
int stringcount=0;
while (string2[stringcount] != '\0')
stringcount++;
return stringcount;
}
int main()
{
char string2[100];
// Initialize the first element to 0
string2[0] = '\0';
printf("Enter a string: \n");
scanf("%99[^\r\n]", &string2[0]);
int length, length2;
length = strlen(string2);
length2 = MyStrlen(string2);
// Change to &string2 to string2
printf("strlen(''%s'') returned %d\n", string2, length);
printf("MyStrlen(''%s'') returned %d\n", string2, length2);
return 0;
}
The output with empty string:
Enter a string:
strlen('''') returned 0
MyStrlen('''') returned 0
The output with "aaa":
Enter a string:
aaa
strlen(''aaa'') returned 3
MyStrlen(''aaa'') returned 3
Well, the problem is with
scanf("%100[^\n]",&string2);
Change it to
fgets (string2, 100, stdin);
Because that scanf cannot read a blank string.
Also, as mentioned in #M.M's comment, check for '\n':
int last = strlen (string2) -1;
if (string2 [last] = '\n') {
string2 [last] = '\0';
}
In the second case I entered a blank string.
The completely corrected code:
#include<stdio.h>
#include<conio.h>
#include<string.h>
int *MyStrlen(const char *string2);
// change the rerturn type to int
int *MyStrlen(const char *string2)
{
int stringcount=0;
while (string2[stringcount] != '\0')
stringcount++;
return stringcount;
}
int main()
{
char string2[100];
// Initialize the first element to 0
string2[0] = '\0';
printf("Enter a string: \n");
fgets (string2, 100, stdin);
int length, length2;
int last = strlen (string2) -1;
if (string2 [last] = '\n') {
string2 [last] = '\0';
}
length = strlen(string2);
length2 = MyStrlen(string2);
printf("strlen(''%s'') returned %d\n", string2, length);
printf("MyStrlen(''%s'') returned %d\n", string2, length2);
return 0;
}
Also as mentioned in #Gomiero's answer, initialize your string to \0.

conflicting types for function returning a char array

Here's my code:
#include <stdio.h>
#include <string.h>
char input_buffer[1000];
void get_substring(){
int i;
int length;
printf("Please enter a string:\n");
scanf("%[^\n]s", input_buffer);
printf("Index of first character of substring:\n");
scanf("%d", &i);
printf("Length of substring:\n");
scanf("%d", &length);
printf("Substring is %.*s ", length, input_buffer + i);
}
int main(void) {
// your code goes here
//get_substring(0,4);
get_substring();
return 0;
}
That's my current code, I want to return a pointer of the input, instead of just displaying the substring. Sorry for the confusion everyone.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getSubstring(char* str,size_t start, size_t length)
{
// determine that we are not out of bounds
if(start + length > strlen(str))
return NULL;
// reserve enough space for the substring
char *subString = malloc(sizeof(char) * length);
// copy data from source string to the destination by incremting the
// position as much as start is giving us
strncpy(subString, str + start, length);
// return the string
return subString;
}
int main(int argc, char* argv[])
{
char *str = "Hallo Welt!";
char *subStr = getSubstring(str,0,20);
if(subStr != NULL)
{
printf("%s\n",subStr);
free(subStr);
}
}
This solution should give you a hint how you would start with such a problem.

Why does this C program crash?

I've mulled over this for at least an hour and I still can't find out what the problem is.
#include <stdio.h>
typedef struct
{
int Level;
char* Name;
} Base;
Base baseStruct;
int main(int argc, char *argv[])
{
scanf("%s", baseStruct.Name);
scanf("%d", &baseStruct.Level);
printf("%s :: Level %d\n", baseStruct.Name, baseStruct.Level);
return 0;
}
What happens is, I go and enter the "Name" string, then when I type and enter the integer the program crashes. What is going on?
scanf("%s", ...)
This expects a buffer (scanf needs to write into it) and you give it an uninitialized pointer, that could point anywhere.
Consider doing one of the following:
Make Name a character buffer instead:
typedef struct
{
int Level;
char Name[100];
} Base;
Initialize it from the heap:
baseStruct.Name = malloc(100); /* do not forget to cleanup with `free()` */
You should also specify max string length in scanf format string to prevent overflow:
/* assume 'Name' is a buffer 100 characters long */
scanf("%99s", baseStruct.Name);
Don't feel bad everyone makes that mistake. The char * stands for a "pointer to a character" but the memory for the string itself is not allocated.
Add:
baseStruct.Name = malloc(sizeof(char)*100);
(note my syntax may be off a little)
Name is just an uninitialized pointer to a string. It doesn't point to anything useful. You'll need to initialize it properly to a string buffer. Also, you may want to limit the string through the formatting (like %100s) to make sure you don't overrun your buffer.
You haven't allocated any storage for Base.Name. You're scanning a string into a a pointer that doesn't point to any storage.
Allocate some space for the string. The problem is that you don't know how big a string will be copied in using scanf. Suppose you malloc 256 bytes and then scanf loads in a 300 byte string? Either allocate a string sufficiently large to handle all possible results from scanf, or modify your scanf to limit the characters, like:
baseStruct.Name = malloc(sizeof(char) * 256);
scanf("%256s", baseStruct.Name);
As others have pointed out, baseStruct.Name does not point to a valid memory region. However, allocating a fixed sized buffer is no safer. For a learning exercise, use
typedef struct
{
int Level;
char Name[1];
} Base;
and enter long strings to examine effects of buffer overflows.
For safe handling of input of indeterminate length, use fgets and sscanf or strtol (or strtoul if Base.Level cannot be negative.
Here is an example:
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INITIAL_BUFSIZE 100
#define MAX_BUFSIZE 30000
char *myreadline(FILE *fin) {
char *buffer;
int offset = 0;
int bufsize = INITIAL_BUFSIZE;
buffer = malloc(bufsize);
if ( !buffer ) {
return NULL;
}
while ( fgets(buffer + offset, bufsize, fin) ) {
size_t last = strlen(buffer) - 1;
if ( buffer[last] == (char) '\n' ) {
buffer[last] = 0;
break;
}
else {
char *tmp;
offset += bufsize - 1;
bufsize *= 2;
if ( bufsize > MAX_BUFSIZE ) {
break;
}
tmp = realloc(buffer, bufsize);
if ( !tmp ) {
break;
}
else {
buffer = tmp;
}
}
}
return buffer;
}
int myreadint(FILE *fin, int *i) {
long x;
char *endp;
char *line = myreadline(fin);
if ( !line ) {
return 0;
}
x = strtol(line, &endp, 10);
if ( (!*endp || isspace((unsigned char) *endp) )
&& (x >= INT_MIN) && (x <= INT_MAX ) ) {
*i = (int) x;
free(line);
return 1;
}
return 0;
}
typedef struct base_struct {
int Level;
char* Name;
} Base;
int main(int argc, char *argv[]) {
Base bs;
int i;
puts("Enter name:");
bs.Name = myreadline(stdin);
if ( !bs.Name ) {
fputs("Cannot read Name", stderr);
return EXIT_FAILURE;
}
puts("Enter level:");
if ( myreadint(stdin, &i) ) {
bs.Level = i;
printf("Name: %s\nLevel: %d\n", bs.Name, bs.Level);
free(bs.Name);
}
else {
fputs("Cannot read Level", stderr);
return EXIT_FAILURE;
}
return 0;
}
Output:
C:\Temp> t
Enter name:
A dark and mysterious dungeon
Enter level:
3456772
Name: A dark and mysterious dungeon
Level: 3456772

Resources