Passing 2 input strings to compare - c

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.");
}

Related

strcpy is not working well with pointer array

#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;
}

How do I concatenate strings via command line arguments separated by a +?

What I want to do is write arguments in the command line separated by a + and concatenate the arguments into a single string
eg:
./concat Wow + this + is + cool
Wow this is cool
I looked up a question for this sort of topic before but that involved concatenating only the first character of each argument and not the entire arguments. And it didn't ignore the separator
This is what I have
void concat(char **argv, int argc, char *string)
{
size_t i = 0;
for(int j=1; j<argc; j++)
{
string[i++] = *argv[j];
if(j+1 != argc)
{
string[i++] = ',';
string[i++] = ' ';
}
}
string[i] = '\0';
}
And this is what I'm doing in main to call this function
int main(int argc, char *argv[])
{
int allnum=0;
char string[1000];
concat(argv, argc, string);
printf("%s\n", string);
}
Using the strcpy or strcat in string.h is more simple to concatenate string.
For example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char * s = malloc (2 * argc *sizeof (char));
if (argc < 2)
exit(-1);
for(int i = 1; i < argc; i += 2) {
strcat(s, argv[i]);
strcat(s, " ");
}
printf("%s\n", s);
return 0;
}

how to fill character pointer array with pointers to strings stored in another array?

I am trying to create a shell, and am having trouble trying to fill the *argv[] array with user input. I call my parse function, and store each word into a 2d array. I tried many different ways to store it directly into *argv[], but eventually decided to try using the 2d array. Is there anyway to fill *argv[] with pointers to the strings stored in the 2d array? Or fill *argv[] with pointers to strings without use of the 2d array?
Ive tried many other things but my current attempt is the while loop after calling the parse function.
int main() {
int status, fRedirect, i;
pid_t pid;
char s[STORAGE];
char p[MAXITEM][STORAGE];
char *argv[MAXITEM];
for(;;) {
printf("\2: ");
scanf("%s", s);
parse(s, p);
while(p[i] != '\0') {
args[i] = *p[i];
}
if(p[0] == EOF)
break;
if(p[0] == '\0')
continue;
pid = fork();
if(pid == 0) {
if(execvp(*p, p) == -1) {
printf("Execution failed!\n");
exit(9);
}
}
if(pid != 0) {
wait(-1, &status, 0);
}
else {
fRedirect = open("/dev/null", O_WRONLY);
dup2(fRedirect, STDOUT_FILENO);
}
}
/*killpg(getpid(), SIGTERM);*/
printf("p2 terminated. \n");
exit(0);
}
void parse(char *s, char p[][STORAGE]) {
int i, j = 0;
while(*s != EOF && *s != '&' && *s != '\n' && *s != ';' && *s != '\0') {
for(i=0; i < strlen(s); i++)
p[j][i] = s[i];
i = i+getword(s);
j++;
}
}
I see in your code that you have included char *argv[MAXITEM]; in the function body of main(). This is traditionally not the way *argv[] is used. The main function definition has code within it that handles memory for *argv[]. Parsing the command line arguments into strings, integers, floating point numbers can be done the usual way, using string parsing and conversion functions inside main(). If you are interested, Here is a post explaining char *argv[] with a little more detail,
For a simple example of string arguments (similar to what you are doing) take a look below at how it is used, it may solve a couple of issues for you right away, such as simplifying the way you are obtaining and parsing your input.
First, the answer to your question: Is there anyway to fill *argv[] with pointers to the strings stored in the 2d array? Or fill *argv[] with pointers to strings without use of the 2d array?
No.
However, you can fill it with string constants. char *Argv[] is itself a variable that can contain an array of strings (pointer to an array of strings) when used in main like this:
#include <ansi_c.h>
int main(int argc, char *argv[]) //Note: the`[]` blank brackets allow any string length.
// the `*` allows multiple arguments
{
int i;
for(i=0;i<argc;i++) //argc contains the count of cmd line arguments
{
printf("%s\n", argv[i]); //*argv[] holds multiple string arguments
}
getchar(); //optional - pauses execution so I can see output
return 0;
}
To test:
Build as play.exe, then run it with command line arguments such as:
"argument1" "argument2" "Hello"
The output should be: (essentially, parsing your input into variable strings)
Ok, after working on it some more and adding in more features, Here is what I'm currently working with. To my knowledge, the parse() command now fills *argv[] with the words taken in from the command line.
int main() {
pid_t pid, child_pid;
int argc, inputRedirect;
char *devNull;
devNull = (char *) malloc(10);
strcpy(devNull, "/dev/null");
char *argv[MAXITEM];
char commandLine[STORAGE];
signal(SIGTERM, myhandler);
for (;;) {
printf("p2: ");
scanf("%s", commandLine);
if(commandLine == EOF)
break;
argc = parse(commandLine, argv);
if (argv[0] == '\0')
continue;
if(argv[0] = "cd")
changeDir(argv[1]);
child_pid = fork();
if (child_pid < 0) {
printf("Cannot fork! Terminating...");
exit(1);
} else if (child_pid == 0) {
CHK(inputRedirect = open(devNull, O_RDONLY));
CHK(dup2(inputRedirect, STDIN_FILENO));
CHK(close(inputRedirect));
CHK(execvp(*argv, argv));
}
else {
for(;;) {
CHK(pid = wait(NULL));
if(pid == child_pid)
break;
}
printf("Child's pid is %d\n", child_pid);
}
}
killpg(getpid(), SIGTERM);
printf("p2 Terminated.\n");
exit(0);
}
int parse(char *commandLine, char *argv[]) {
int argc = 0;
char *commandPointer = commandLine;
while (*commandPointer != '\0') {
*argv = commandPointer;
argc++;
getword(commandPointer);
}
*commandPointer = '\0';
*argv = '\0';
return argc;
}

How can I stop scanf-ing input after a certain character?

I'm working on a function that takes filepaths and dices them up into smaller sections.
For example, if the input parameter was "cd mypath/mystuff/stack/overflow/string", I want to be able to return "cd" "mypath", "mystuff", "stack", "overflow", and "string" in succession.
While I could simply continually use "getchar", appending the results to an ever-increasing string, stopping when getchar returns a '/', I feel like there must be a more elegant way to achieve the same functionality.
Any ideas?
You can use the char * strtok ( char * str, const char * delimiters ); using / as separator.
An example here:
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s path\n", argv[0]);
exit(EXIT_FAILURE);
}
char* saveptr = NULL;
for (char* str = argv[1]; ; str = NULL) {
char *token = strtok_r(str, "/", &saveptr);
if (token == NULL)
break;
printf("%s\n", token);
}
return 0;
}
Example
clang -Wall *.c && ./a.out mypath/mystuff/stack/overflow/string
mypath
mystuff
stack
overflow
string
Here's an example of how sscanf() can stop after a certain character.
sscanf("abcd/efgh", "%[^/]", &buf);
printf("%s\n", buf);
Should produce
abcd
EDIT: You could try something like this to advance sscanf() input. I have not tested this for various edge cases, but it should get the idea across.
char *str = "abcd/efgh/ijk/xyz";
while (sscanf(str, "%[^/]%n", &buf, &n)) {
printf("%s\n", buf);
str += n;
if (*str == '\0')
break;
++str;
}
should produce
abcd
efgh
ijk
xyz
Here is an example using regcomp, regexec. Compile and run it with the first arg being the character you are searching on, while the second arg is the string to search.
For example, a.out X abcXdefXghiXjkl will print abc def ghi jkl on separate lines.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <regex.h>
int
main(int argc, char *argv[]) {
int len;
char *cp;
char *token;
regex_t preg;
regmatch_t match;
if (regcomp(&preg, argv[1], REG_EXTENDED) != 0) {
return 0;
}
for (cp = argv[2]; *cp != '\0'; cp += len) {
len = (regexec(&preg, cp, 1, &match, 0) == 0) ? match.rm_eo : strlen(cp);
token = malloc(len);
strncpy(token, cp, len);
printf("%s\n", token);
}
return 0;
}

Default command line arguments in C

$ ./Main a
int main(int argc, char * argv[]) {
int i;
for(i=1;i<argc;i++){
if(argv[i] == NULL){ //This line does not work!
argv[i] = "Null";
}
}
theMenu(argv[1], argv[2], argv[3], argv[4]);
return (EXIT_SUCCESS);}
In theMenu function,when I called strcmp(argv[2],argv[3]); I will have segmentation fault :((
How can I make argv[x] = "Null" when user did not enter the parameter at x?
The CRT will not insert NULL entries for arguments you didn't receive. It will simply reduce the value of argc instead. If you must have four arguments, then you can define your own array on the stack.
int main(int argc, char * argv[]) {
char* args[4] = { 0 };
int i;
for(i=1;i<argc && i < 4;i++){
args[i] = argv[i];
}
for(int i = 0; i < 4; i++) {
if (args[i] == NULL)
args[i] = "Null";
}
theMenu(argv[1], argv[2], argv[3], argv[4]);
return (EXIT_SUCCESS);
}
You can't. What you can do is define your own array of size [4] initialized to empty strings or NULLs and copy arguments (up to argc count) there.
Your problem is that argc<5 and so you are attempting to access elements of argv that are not defined.
You're expecting 4 arguments. Why not trap it like so:
if (argc==5)
{
//code here
}
(it is 5 because there is an arg[0] when you run your code)

Resources