Printf() showing strange characters

Asked

Viewed 90 times

0

The purpose of the code is to show all substrings of the variable firstString that has the same size as the second string that is the variable secondString. However, when I use the printf("%s\n", pieceOfFirstString); shows that the string has some strange characters, and I do not know where these characters are coming from (which interferes with other logic of the program), I have read and reread the code several times, probably is something I do not understand yet.
Exceptional cases such as, second string larger than the first and strings of same size have been covered in the original code, this is a minimum verifiable example.

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

const int STRING_MAX_SIZE = 100;

int main()
{
    char firstString[STRING_MAX_SIZE];
    char secondString[STRING_MAX_SIZE];
    scanf("%s\n%s", firstString, secondString);

    int sizeFirstString = strlen(firstString);
    int sizeSecondString = strlen(secondString);

    char pieceOfFirstString[sizeSecondString];
    for (int firstCharIndex = 0; sizeFirstString - firstCharIndex >= sizeSecondString; firstCharIndex++)
        for (int lastCharIndex = firstCharIndex + 1; lastCharIndex - firstCharIndex != sizeSecondString; lastCharIndex++)
        {
            int sizeOfPiece = (lastCharIndex - firstCharIndex) + 1;

            if (sizeOfPiece == sizeSecondString)
            {
                strncpy(pieceOfFirstString, firstString + firstCharIndex, sizeOfPiece);
                
                printf("%s\n", pieceOfFirstString);
            }
        }

    system("pause");
    return 0;
}

A different piece of code I used and worked out was using argc and argv to read strings:

int main(int argc, char *argv[])
{
    char* firstString = argv[1];
    char* secondString = argv[2];

    int sizeFirstString = strlen(firstString);
    int sizeSecondString = strlen(secondString);

    // (...) Continua lógica do outro pedaço de código.
}

But I want the code to work using scanf();.

An example of input to test code firstString, secondString, in that order, and the outputs, current (with error), ideal (without any kind of error).
Input (For example):

abababa
ab

Output (Current):
Using the scanf(); to read the variables.

ab▒▒b
ba▒▒b
ab▒▒b
ba▒▒b
ab▒▒b
ba▒▒b

Output (Ideal):
Using the argc and argv to read the variables.

ab
ba
ab
ba
ab
ba

Summary of the problem: I don’t know why the result of the algorithm changes with the type of reading of the variables firstString and secondString, and what I need is that the result of the algorithm using reading with scanf(); is the same as the result of reading with argc and argv.

  • Could you better define what you are trying to do? What are substrings of a string? Permutations of any size? Or does it refer to occurrences of the second string in the first string? In what way? What would it be? I didn’t understand the example nor the argc/argv thing. What does execution parameters have to do with substrings? Is it another way to enter 2 strings into the program? What changes in the program?

  • I tried to define it better, I hope now to understand. argc/argv was just a different way I know to read the variables, which, I do not know why, worked properly, while using scanf does not work.

  • If the purpose of the code is to show all substrings of the variable firstString that has the same size as the second string that is the variable secondString, take a look in this example which is a much simpler option to perform the same task.

2 answers

0


The function strncpy does not put the \0 at the end of the copy when the amount of characters to be copied is less than the copied string.

Try this:

if (sizeOfPiece == sizeSecondString)
{
    strncpy(pieceOfFirstString, firstString + firstCharIndex, sizeOfPiece);
    pieceOfFirstString[sizeOfPiece] = '\0';
    printf("%s\n", pieceOfFirstString);
}

0

"The purpose of the code is to show all substrings of the variable firstString that has the same size of the second string that is the variable secondString"

For what you say you need to do just the size of the second string, since nothing will be used.

So you can just determine its size and a pointer to the beginning of the substring, and go "floating" one zero by the input as the result terminator.

Take an example

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

int main(int argc, char** argv)
{
    char first [100];
    char second[100];
    int  res = 0;
    if (argc == 3)
    {   // aceita os argumentos se vieram dois
        strcpy(first, argv[1]);
        strcpy(second, argv[2]);
    }
    else
    {   // cancela se nao ler duas strings
        printf("Entre com as duas strings: ");
        int res = scanf("%s %s", first, second);
        if (res != 2) return -1;
    }   // if()
    size_t len = strlen(second);
    size_t n   = strlen(first) - len;
    printf(
        "\
Strings consideradas: 1: \"%s\" e \"%s\"\n\n\
substrings de \"%s\" de tamanho %zd: { ", 
        first, second, first, len );
    char save = 0;
    char* p    = first;
    for (int i = 0; i < n; i += 1, p+= 1)
    { 
        save = *(p + len);
        *(p + len) = 0;
        printf("\"%s\"  ", p);
        *(p + len) = save;
    }
    printf("\"%s\" }\n", p); // o ultimo
    return 0;
}

In this case you can use both options: either you enter the two strings on the command line or the program asks later:


PS> ./f0-0817
Entre com as duas strings: abababa ab
Strings consideradas: 1: "abababa" e 2: "ab"

substrings de "abababa" de tamanho 2: { "ab"  "ba"  "ab"  "ba"  "ab"  "ba"  }

PS> ./f0-0817 abababa ab
Strings consideradas: 1: "abababa" e 2: "ab"

substrings de "abababa" de tamanho 2: { "ab"  "ba"  "ab"  "ba"  "ab"  "ba"  }


This loop extracts the values

    char save = 0;
    char* p    = first;
    for (int i = 0; i < n; i += 1, p+= 1)
    { 
        save = *(p + len);
        *(p + len) = 0;
        printf("\"%s\"  ", p);
        *(p + len) = save;
    }

It’s simpler to write like this.

If you cannot use C pointers

No pointers of course the same thing, it’s just harder to read and needs an extra loop because it can’t pass the new initial address to printf(). Because? Because it would be clear a char*.
In C vectors are base + offset. So this code does the same thing as in the above example, but without the pointers:

    char  save = 0;
    size_t  ix = 0;
    for (int i = 0; i <= n; i += 1, ix += 1)
    {
        save       = first[ix+len];
        first[ix+len] = 0;
        printf("\"");
        for (size_t j = ix; j<ix+len; j += 1)
            printf("%c ", first[j]);
        printf("\" ");
        first[ix+len] = save;
    }
    printf("}\n");  // o ultimo

Exit this case by using your data

If you enter two parameters the program uses these two


PS> ./f1-0817
Entre com as duas strings: abababa ab
Strings consideradas: 1: "abababa" e 2: "ab"

substrings de "abababa" de tamanho 2: { "ab" "ba" "ab" "ba" "ab" "ba" }

PS> ./f1-0817 abababa ab
Strings consideradas: 1: "abababa" e 2: "ab"

substrings de "abababa" de tamanho 2: { "ab" "ba" "ab" "ba" "ab" "ba" }

The complete program, which uses no pointers

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

int main(int argc, char** argv)
{
    char first[100];
    char second[100];
    int  res = 0;
    if (argc == 3)
    {  // aceita os argumentos se vieram dois
        strcpy(first, argv[1]);
        strcpy(second, argv[2]);
    }
    else
    {  // cancela se nao ler duas strings
        printf("Entre com as duas strings: ");
        int res = scanf("%s %s", first, second);
        if (res != 2) return -1;
    }  // if()
    size_t len = strlen(second);
    size_t n   = strlen(first) - len;
    printf(
        "\
Strings consideradas: 1: \"%s\" e \"%s\"\n\n\
substrings de \"%s\" de tamanho %zd: { ",
        first, second, first, len);
    char  save = 0;
    size_t  ix = 0;
    for (int i = 0; i <= n; i += 1, ix += 1)
    {
        save       = first[ix+len];
        first[ix+len] = 0;
        printf("\"");
        for (size_t j = ix; j<ix+len; j += 1) printf("%c ", first[j]);
        printf("\" ");
        first[ix+len] = save;
    }
    printf("}\n");  // o ultimo
    return 0;
}

If you need to look for something in the first string based on the second string I think in general the simplest is to use a state machine.

About your program

const int STRING_MAX_SIZE = 100;

int main()
{
    char firstString[STRING_MAX_SIZE];

You cannot declare this by default. the vector size has to be known at compile time.

    scanf("%s\n%s", firstString, secondString);

Consider helping who will use the program by explaining what it is to do with the cursor standing there waiting for two strings.

And test ALWAYS the return of scanf(). What’s the point of following the program if you don’t read both strings?

    for (int firstCharIndex = 0;
         sizeFirstString - firstCharIndex >= sizeSecondString;
         firstCharIndex++)
        for (int lastCharIndex = firstCharIndex + 1;
             lastCharIndex - firstCharIndex != sizeSecondString;
             lastCharIndex++)

Avoid names that big. It’s just hard to read.

  • Its code does not satisfy as an answer because it does not solve my problem: "what I need is that the result of the algorithm using scanf() reading; be the same as the result of reading with argc and argv." The reply from @Vander Santos did, and I did not specify but could not use pointers. On the names of the variables I believe it is good practice, that the code becomes much easier to read and be understood.

  • I still don’t understand: the program I showed you not only gives the same result as you can test then, using or not argc and argv. In the same code. And no need to copy PiecesOfFirstString to nowhere, just manipulate the indexes. : ) pity that did not help you. If you have any time left I show you how to do without using pointers. spoiler: is the same thing. It’s just harder to read without the pointers. C arrays are just that: base + offset. Just swap the pointers for the sum.

  • Not being able to use C pointers is a very strange constraint, and you really should have said you couldn’t use them. Who would have thought?

  • In times of pandemic I do not leave the office anyway. : ) I put an example of how you can do without pointers, in C.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.