#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr;
char temp[20];
if (strlen(argv[1]) < strlen(argv[2]))
{
strcpy(temp,argv[1]);
strcpy(argv[1],argv[2]);
strcpy(argv[2],temp);
}
ptr = strstr(argv[1],argv[2]);
if (ptr == NULL)
printf("Non-inclusive");
else
printf("%s is part of %s", argv[2], argv[1]);
return 0;
}
When I enter "abc abcd",
I want to get "abc is part of abcd" as a result,
but real result is "abc is part of abcdabc"
The length of each string in the argv array is fixed. So when you attempt to swap the contents of argv[1] and argv[2] when their sizes are different you write past the end of the shorter one. This triggers undefined behavior.
Better to use separate char * variables, one pointing the longer string and one pointer to the shorter.
int main(int argc, char *argv[])
{
char *ptr;
char *s_short, *s_long;
if (strlen(argv[1]) < strlen(argv[2])) {
s_short = argv[1];
s_long = argv[2];
} else {
s_short = argv[2];
s_long = argv[1];
}
ptr = strstr(s_long,s_short);
if (ptr == NULL)
printf("Non-inclusive");
else
printf("%s is part of %s", s_short, s_long);
return 0;
}
I am new to C and I have had trouble simplifying this program. I am trying to initalize name once and strcat name to command once. It is a command line executable that takes two args and one optional arg for the filename "new py" or "new txt", or "new py script". I run Windows's MinGW to compile.
Is there a type to allow storage of argv value and a string constant with one line?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char command[100] = "cd . > ";
char *type = argv[1];
char * name;
strcat(command,"\"");
if (argc == 3) {
char * name = argv[2];
//strcat(command,name);
} else {
char name[20];
sprintf(name,"new %s file",type);
//strcat(command,str);
}
strcat(command,name);
strcat(command,".");
strcat(command,type);
strcat(command,"\"");
system(command);
return 0;
}
As mentioned by BLUEPIXY, my block needs to include "char name[20]; if(argc == 3){ strcpy(name, argv[2]); } else { sprintf(name,"new %s file",type); } strcat(command, name);". After those changes, I converted all of the strcats to one sprinf.
My previous understanding of storing argv items was that char pointers were needed for compilation because args wouldn't be defined. They are not needed any more because of the initialization of name.
My now condensed code is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char command[100];
char * type = argv[1];
char name[50];
if (argc == 3) {
strcpy(name, argv[2]);
} else {
sprintf(name,"new %s file",type);
}
sprintf(command,"cd . > \"%s.%s\"",name,type);
system(command);
return 0;
}
Again, thank you BLUEPIXY for clearing my misunderstanding.
New in C and pretty confused about how to deal with several strings at the same time using strtok, for a simply example, I want to use strtok to extract the number and compare then.
#include <stdio.h>
#include <string.h>
int main()
{
char s1[100]="11.54";
char s2[100]="12.55";
const char tok[2]=".";
char* token1=strtok(s1,tok);
char* token2=strtok(s2,tok);
while(token1 !=NULL && token2 !=NULL){
int temp=strcmp(token1,token2);
if(temp==0){
token1=strtok(NULL,tok);
token2=strtok(NULL,tok);
}
else if(temp<0){
printf("%d\n",-1);
return;
}
else{
printf("%d\n",1);
return;
}
}
if(token1 !=NULL){
printf("%d\n",1);
return;
}
if(token2 !=NULL){
printf("%d\n",-1);
return;
}
printf("%d\n",0);
return 0;
}
But when I use the strtok, the strtok(NULL,token)will point to the current string and will do like: 11->12>55->NULL and skip the 54
How could I deal with such situation? Thanks!!
Do not use strtok(). The documentation will tell you strtok() is not reentrant (i.e. should not be used across threads), but perhaps less obvious is the fact that the reason it is not reentrant is because it uses an internal save variable to remember where it's got to. That means you also can't use two instances at once. Instead use strtok_r() or failing that strsep() might work.
strtok_r() is just like strtok, save that you pass it a char ** (i.e. a pointer to char *) where it can save where it's got to.
The GNU libc manual page gives a good example of using a nested strtok_r which is what you are trying to do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
char *str1, *str2, *token, *subtoken;
char *saveptr1, *saveptr2;
int j;
if (argc != 4) {
fprintf(stderr, "Usage: %s string delim subdelim\n",
argv[0]);
exit(EXIT_FAILURE);
}
for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
token = strtok_r(str1, argv[2], &saveptr1);
if (token == NULL)
break;
printf("%d: %s\n", j, token);
for (str2 = token; ; str2 = NULL) {
subtoken = strtok_r(str2, argv[3], &saveptr2);
if (subtoken == NULL)
break;
printf(" --> %s\n", subtoken);
}
}
exit(EXIT_SUCCESS);
}
I'm testing a small program which basically compares whether 2 input strings are identical (as strcmp does).
I'd want to do something like (users type 2 desired strings on the same line). In this case it should return "The two strings are different"
./a.out foo bar
should I do this to read the user's input strings?
scanf("%s %s", str1, str2);
or
gets(str1); gets(str2);
Here is what I have so far (it seems to stuck in an infinite loop for some reasons)
int mystrcmp(char str1[], char str2[]) {
int i = 0;
while (str1[i] == str2[i]) {
if (str1[i] == '\0' || str2[i] == '\0') break;
i++;
}
if (str1[i] == '\0' && str2[i] == '\0')
return 0;
else
return -1;
}
int main(int argc, char * * argv) {
int cmp;
char str1[1000], str2[1000];
scanf("%s %s", str1, str2);
//gets(str1); gets(str2);
cmp = mystrcmp(str1, str2);
if (cmp == 0)
printf("The two strings are identical.\n");
else
printf("The two strings are different.\n");
return 0;
}
You should do neither. Instead I suggest you learn about how command line arguments are passed to the main function through the argc and argv arguments.
I suggest you try this program to help your understanding:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("argc = %d\n", argc);
for (int a = 0; a < argc; ++a)
printf("argv[%d] = \"%s\"\n", a, argv[a]);
}
For your example invocation
./a.out foo bar
the program above will print
argc = 3
argv[0] = "./a.out"
argv[1] = "foo"
argv[2] = "bar"
This solution should work:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
if(argc != 3) {
puts("Wrong number of arguments");
return 0;
}
if(strcmp(argv[1], argv[2]))
puts("The two strings are different.");
else
puts("The two strings are identical.");
}
How do I add two strings?
I tried name = "derp" + "herp";, but I got an error:
Expression must have integral or enum type
C does not have the support for strings that some other languages have. A string in C is just a pointer to an array of char that is terminated by the first null character. There is no string concatenation operator in C.
Use strcat to concatenate two strings. You could use the following function to do it:
#include <stdlib.h>
#include <string.h>
char* concat(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}
This is not the fastest way to do this, but you shouldn't be worrying about that now. Note that the function returns a block of heap allocated memory to the caller and passes on ownership of that memory. It is the responsibility of the caller to free the memory when it is no longer needed.
Call the function like this:
char* s = concat("derp", "herp");
// do things with s
free(s); // deallocate the string
If you did happen to be bothered by performance then you would want to avoid repeatedly scanning the input buffers looking for the null-terminator.
char* concat(const char *s1, const char *s2)
{
const size_t len1 = strlen(s1);
const size_t len2 = strlen(s2);
char *result = malloc(len1 + len2 + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
memcpy(result, s1, len1);
memcpy(result + len1, s2, len2 + 1); // +1 to copy the null-terminator
return result;
}
If you are planning to do a lot of work with strings then you may be better off using a different language that has first class support for strings.
#include <stdio.h>
int main(){
char name[] = "derp" "herp";
printf("\"%s\"\n", name);//"derpherp"
return 0;
}
David Heffernan explained the issue in his answer, and I wrote the improved code. See below.
A generic function
We can write a useful variadic function to concatenate any number of strings:
#include <stdlib.h> // calloc
#include <stdarg.h> // va_*
#include <string.h> // strlen, strcpy
char* concat(int count, ...)
{
va_list ap;
int i;
// Find required length to store merged string
int len = 1; // room for NULL
va_start(ap, count);
for(i=0 ; i<count ; i++)
len += strlen(va_arg(ap, char*));
va_end(ap);
// Allocate memory to concat strings
char *merged = calloc(sizeof(char),len);
int null_pos = 0;
// Actually concatenate strings
va_start(ap, count);
for(i=0 ; i<count ; i++)
{
char *s = va_arg(ap, char*);
strcpy(merged+null_pos, s);
null_pos += strlen(s);
}
va_end(ap);
return merged;
}
Usage
#include <stdio.h> // printf
void println(char *line)
{
printf("%s\n", line);
}
int main(int argc, char* argv[])
{
char *str;
str = concat(0); println(str); free(str);
str = concat(1,"a"); println(str); free(str);
str = concat(2,"a","b"); println(str); free(str);
str = concat(3,"a","b","c"); println(str); free(str);
return 0;
}
Output:
// Empty line
a
ab
abc
Clean-up
Note that you should free up the allocated memory when it becomes unneeded to avoid memory leaks:
char *str = concat(2,"a","b");
println(str);
free(str);
I'll assume you need it for one-off things. I'll assume you're a PC developer.
Use the Stack, Luke. Use it everywhere. Don't use malloc / free for small allocations, ever.
#include <string.h>
#include <stdio.h>
#define STR_SIZE 10000
int main()
{
char s1[] = "oppa";
char s2[] = "gangnam";
char s3[] = "style";
{
char result[STR_SIZE] = {0};
snprintf(result, sizeof(result), "%s %s %s", s1, s2, s3);
printf("%s\n", result);
}
}
If 10 KB per string won't be enough, add a zero to the size and don't bother, - they'll release their stack memory at the end of the scopes anyway.
You should use strcat, or better, strncat. Google it (the keyword is "concatenating").
You cannot add string literals like that in C. You have to create a buffer of size of string literal one + string literal two + a byte for null termination character and copy the corresponding literals to that buffer and also make sure that it is null terminated. Or you can use library functions like strcat.
Concatenate Strings
Concatenating any two strings in C can be done in atleast 3 ways :-
1) By copying string 2 to the end of string 1
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
int i,j=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=strlen(str1);str2[j]!='\0';i++) //Copying string 2 to the end of string 1
{
str1[i]=str2[j];
j++;
}
str1[i]='\0';
printf("\nConcatenated string: ");
puts(str1);
return 0;
}
2) By copying string 1 and string 2 to string 3
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX],str3[MAX];
int i,j=0,count=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=0;str1[i]!='\0';i++) //Copying string 1 to string 3
{
str3[i]=str1[i];
count++;
}
for(i=count;str2[j]!='\0';i++) //Copying string 2 to the end of string 3
{
str3[i]=str2[j];
j++;
}
str3[i]='\0';
printf("\nConcatenated string : ");
puts(str3);
return 0;
}
3) By using strcat() function
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
strcat(str1,str2); //strcat() function
printf("\nConcatenated string : ");
puts(str1);
return 0;
}
Without GNU extension:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
res = malloc(strlen(str1) + strlen(str2) + 1);
if (!res) {
fprintf(stderr, "malloc() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
strcpy(res, str1);
strcat(res, str2);
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
Alternatively with GNU extension:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
if (-1 == asprintf(&res, "%s%s", str1, str2)) {
fprintf(stderr, "asprintf() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
See malloc, free and asprintf for more details.
#include <string.h>
#include <stdio.h>
int main()
{
int a,l;
char str[50],str1[50],str3[100];
printf("\nEnter a string: ");
scanf("%s",str);
str3[0]='\0';
printf("\nEnter the string which you want to concat with string one: ");
scanf("%s",str1);
strcat(str3,str);
strcat(str3,str1);
printf("\nThe string is %s\n",str3);
}
using memcpy
char *str1="hello";
char *str2=" world";
char *str3;
str3=(char *) malloc (11 *sizeof(char));
memcpy(str3,str1,5);
memcpy(str3+strlen(str1),str2,6);
printf("%s + %s = %s",str1,str2,str3);
free(str3);
my here use asprintf
sample code:
char* fileTypeToStr(mode_t mode) {
char * fileStrBuf = NULL;
asprintf(&fileStrBuf, "%s", "");
bool isFifo = (bool)S_ISFIFO(mode);
if (isFifo){
asprintf(&fileStrBuf, "%s %s,", fileStrBuf, "FIFO");
}
...
bool isSocket = (bool)S_ISSOCK(mode);
if (isSocket){
asprintf(&fileStrBuf, "%s %s,", fileStrBuf, "Socket");
}
return fileStrBuf;
}
In C, you don't really have strings, as a generic first-class object. You have to manage them as arrays of characters, which mean that you have to determine how you would like to manage your arrays. One way is to normal variables, e.g. placed on the stack. Another way is to allocate them dynamically using malloc.
Once you have that sorted, you can copy the content of one array to another, to concatenate two strings using strcpy or strcat.
Having said that, C do have the concept of "string literals", which are strings known at compile time. When used, they will be a character array placed in read-only memory. It is, however, possible to concatenate two string literals by writing them next to each other, as in "foo" "bar", which will create the string literal "foobar".