-2

Hello so i don't have any friends who could help me i get this eror when i test this code look what i have already done

./main "Hello World!" "ld"
-bash: !": event not found

what is this what is happening

here is the main :

#include <stdio.h>
#include <err.h>
#include <string.h>
int main (int argc, char *argv[]) 
{

int p = 0;
int q = 1;
int place = 0;
int check = 0;
char position[10] = ""; // i think the error is here

while (argv[1][p] != '\0')
{
    if (argv[1][p] == argv[2][0])
    {
        place = p;
        while (argv[2][q] != '\0' && argv[1][p + q] != '\0' && argv[2][q] == argv[1][p + q])
            { 
            q += 1;
            }
        if (argv[2][q] == '\0')
        {
            check = 1;
            printf("%s\n", argv[1]); //i think the error is here
            for (int n = 0; n < place; n += 1) //i think the error is here
            {
                strcat(position, " "); //i think the error is here
            }
            strcat(position, "^"); //i think the error is here
            printf("%s\n", position); //i think the error is here

        }
    }
    p += 1;
}
if (check == 0)
{
    printf("Not found!\n");
}

return 0 ; // return 0
}

I added comment so you can maybe help

and also how can I create

char position[10] = "";

without giving the length I tried

char position[] = "";

but it doesn't compile

CUCKY55
  • 1
  • 3
  • Is this a bash script? What is your first line, `#!/bin/bash`? You're probably missing `#`. – Fiddling Bits Nov 20 '18 at 13:19
  • Exactly what have you done? Is `main` the result of compilation of a program in C? If so where is the source code? – roschach Nov 20 '18 at 13:21
  • I test my function using ./main "Hello World!" "ld" because I give 2 arguments – CUCKY55 Nov 20 '18 at 13:22
  • I cannot post the source code this website tell me I cannot post it because it is a huge code of 10 lines – CUCKY55 Nov 20 '18 at 13:22
  • It looks like your post is mostly code; please add some more details. – CUCKY55 Nov 20 '18 at 13:23
  • What does `echo "Hello World!"` do? I suspect it will give you the same "event not found" error. Try it with single quotes instead of double quotes. – Ian Abbott Nov 20 '18 at 13:24
  • but my boss tell me he will try the main function like this with " " and not nothing why me – CUCKY55 Nov 20 '18 at 13:25
  • Could you include your "#include" statements so that we can compile the program? – Gardener Nov 20 '18 at 13:26
  • i add it. but i think it is because i try ./main with "Hello World!" and the ! is not recognized maybe – CUCKY55 Nov 20 '18 at 13:29
  • 1
    I don't think the problem is caused by your C program. It is caused by the Bash shell. – Ian Abbott Nov 20 '18 at 13:31
  • A ok nice now my last error please see last edit (about char position) – CUCKY55 Nov 20 '18 at 13:32
  • @IanAbbott no the call is correct try `ls "Hello World!" "ld"` or see bottom of [this](https://www.tutorialspoint.com/cprogramming/c_command_line_arguments.htm) – Welgriv Nov 20 '18 at 13:44
  • `char position[] = "";` will create the `position` array with length 1 (just enough room to store an empty, null-terminated string). It should compile fine. But some of your other code, such as `strcat(position, " ");` would then result in *undefined behavior* because the `position` array is too short to hold the resulting null-terminated string. Perhaps your compiler is smart enough to detect that and report an error. – Ian Abbott Nov 22 '18 at 13:03

2 Answers2

3

Short Answer

With exclamation points, use single quotes.

./main 'Hello World!' 'ld'

Long Answer

The exclamation mark does something funny in Bash. Read more... unix.stackexchange.

The exclamation mark is part of history expansion in bash. To use it you need it enclosed in single quotes.

Even trying !" with echo gives

$ echo "Hello World!"
-bash: !: event not found

You could use double quotes, but you may need a blackslash.

Note that in double quotes, a backslash before the exclam prevents history expansion, BUT the backslash is not removed in such a case.

So ./main "Hello World\!" "ld" would also work, but you might need to account for the blackslash within your C/C++.

Note that the behaviour of the exclamation point may have changed. Executing echo "Hello World!" make work on some bash versions. Credits to Benjamin W.

TrebledJ
  • 8,713
  • 7
  • 26
  • 48
  • Escaping things with a backslash doesn't mean the backslash is also passed to the C code, so either option will have the same result – Chris Turner Nov 20 '18 at 14:03
  • It's maybe worth to mention that the behaviour of `!` within double quotes changed at some point: in Bash 4.3, you can use `echo "hello!"`(exclamation point directly before closing double quote) without problems, but in Bash 4.2, you'd have to use single quotes or escape the exclamation point. When escaping, the backslash won't be removed, so single quotes are the better bet. – Benjamin W. Nov 20 '18 at 14:33
  • @ChrisTurner If you look at the output of `echo "hello\!"`, you'll see that the backslash is _not_ removed, so the result might differ. – Benjamin W. Nov 20 '18 at 14:34
  • @BenjaminW. odd...maybe that is something else that changed? although it is only an issue if the parameter is in quotes so `echo hello\!` works as I'd expect – Chris Turner Nov 20 '18 at 14:44
  • @ChrisTurner I think the escaping behaviour of `!` differs in- and outside of double quotes. – Benjamin W. Nov 20 '18 at 16:49
0

I think that the "!" maybe causing some problems with your bash shell. I ran it in mine without any problems. If you try my code and it fails, try running it as

./main "Hello World" ld

The logic in your code is confusing because you are trying to use the argv[1] and argv[2] inputs directly. it can be done, but the way that it is written is very difficult to follow.

I have reduced the complexity of the code by renaming the variables so that you can follow the logic more easily.

I also add a sub-routine to carry out the string compare. Of course, there is a library strcmp() function, I am not sure if you avoided that function because of some requirement. You could modify this to use the std strcmp().

Good code should be documented by the names of the variables. Here is what I came up with:

#include <stdio.h>
#include <string.h>

/* compare two c strings.  Return 0 if equivalent. Return -1 if not.
 * Assumes that the strings are terminated with a '\0' character */
int homegrown_strcmp(char* str1, char* str2) {

    while( *str2 != '\0') {
        if(*str1 != *str2)
            return -1;
        str1++;
        str2++;
    }
    return 0;

}

int main(int argc, char *argv[])
{


    char* haystack = argv[1]; /* This is the string we are searching inside */
    char* needle = argv[2]; /* This is what we are looking for */

    char* poker = haystack;  /* We will use this to poke into our haystack until
 * we find our needle or fail */

    unsigned int position = 0;
    while(*poker != '\0') {
        if(homegrown_strcmp(poker, needle) == 0) {
            printf("Found at position %u\n", position);
            return 0;
        }
        poker++;
        position++;
    }
    printf("Not found\n");
    return -1;
}
Gardener
  • 2,591
  • 1
  • 13
  • 22
  • thanks it will help me but I avoided pointers on purpose.. just tell me how could i fix my code and create an automatic length string where i can concatenate as many spaces as i want – CUCKY55 Nov 20 '18 at 14:00
  • The reason I rewrote the code is that I could not follow your code. If you look closely, you will see that I carefully identified the needle, the haystack, and the poker. You can do the same with your code, but it is harder. If you want to solve it using char arrays, then you would be advised to rename your indices so that it is easier to follow. For example, use p => poker_index, q => needle_index, check should be a boolean called "is_found" and so forth. I am not smart enough to debug code without renaming the variables. Hope that helps. – Gardener Nov 20 '18 at 15:22