Je suis actuellement en train de résoudre un problème simple sur codeforce. En gros, une chaîne vous est donnée (par exemple "1 + 3 + 2") et vous devez la renvoyer triée (par exemple "1 + 2 + 3"). Seuls 1,2 et 3 seront utilisés.

J'ai commencé avec:

#include <iostream>
using namespace std;    

int main()
{
    string str;
    int arr[4];
    cin >>str;    

    for(int i = 0; i < str.length();i+=2)
        arr[str[i] - '0']++;    
}

Mon idée était de stocker chaque occurrence d'un nombre dans un tableau. Mais j'ai remarqué un problème si j'ajoutais

cout<< arr[2];

Et entrée "1 + 2 + 3", il sort:

33

Cependant, il devrait être 1, car 3 ne s'est produit qu'une seule fois.

Je l'ai résolu, en déplaçant "string str;" et "int arr [4]" vers le haut, sur main:

#include <iostream>
using namespace std;

string str;
int arr[4];

int main()
{   
    cin >>str;

    for(int i = 0; i < str.length();i+=2)
        arr[str[i] - '0']++;
    cout<< arr[2];
}

Production:

1

Pourquoi ça marche maintenant?

0
unbekantus WuUS 28 août 2020 à 13:53

3 réponses

Meilleure réponse

Durée de stockage automatique sans initialiseur: l'initialisation par défaut s'applique: un tableau de type fondamental non-classe restera avec des valeurs non initialisées

Dans votre premier exemple, arr a une durée de stockage automatique et n'est pas initialisé, suite à l'initialisation par défaut:

int main() {
    // default initialization
    int arr[4];

    // reading from arr at this point (remains
    // uninitialized) is undefined behaviour.
}

L'effet de l'initialisation par défaut d'un type de tableau est que chaque élément du tableau est initialisé par défaut. L'effet de l'initialisation par défaut sur les types non-classes fondamentaux n'est rien: les éléments resteront non initialisés. La lecture à partir de ces éléments (invocation de operator++ sur les éléments de votre exemple) est un comportement indéfini.

Vous pouvez par exemple value-initialize arr en utilisant la syntaxe suivante:

int main() {
    int arr[4]{};
}

Avec pour effet que chaque élément du tableau est initialisé par la valeur, ce qui a pour effet que chaque élément du tableau (type fondamental sans classe) est initialisé à zéro.


Durée de stockage statique: l'initialisation zéro s'applique

Dans le deuxième exemple, arr n'a plus de durée de stockage automatique mais une durée de stockage statique, et les règles d'initialisation statique s'appliquent, ce qui entraînera l'initialisation de arr à zéro.

0
dfrib 28 août 2020 à 21:04

C ++ n'initialise pas les tableaux à 0 par défaut. Votre contenu initial est imprévisible, tout comme vos résultats.

Il existe plusieurs façons de résoudre le problème. Je suggérerais d'utiliser std :: vector , déclarant la variable comme:

#include <vector>
std::vector<int> arr(4, 0); 

Le premier paramètre est la taille, le second est la valeur initiale de tous les éléments (0 est la valeur par défaut). Vous pouvez simplement l'utiliser comme un tableau avec []. Il a d'autres fonctionnalités utiles, peut s'agrandir par exemple si nécessaire.

Vous pouvez également utiliser memset pour effacer le tableau:

#include <cstring>
memset(arr, 0, sizeof(arr));

Cette fonction est plus ancienne et vous avez besoin de plus de soin.

0
Audrius Meskauskas 28 août 2020 à 11:14

Vous n'avez pas initialisé int arr[4]; dans votre premier exemple. En tant que tel, le comportement de votre programme n'est pas défini.

Si vous imprimez le contenu de arr sans votre première boucle for:

for (auto x: arr) {
  std::cout << x << "\n";
}

Vous obtenez des données inutiles qui se trouvent à l'adresse de arr:

121
32584
615125669
22063

Mais vous n'êtes pas assuré d'obtenir quoi que ce soit. Si vous fournissez au compilateur un programme invalide, il est autorisé à faire tout ce qu'il veut.


Vous pouvez résoudre ce problème en initialisant votre baie:

int arr[4] = {};

Cela valorisera l'initialisation du tableau, ce qui pour int signifie l'initialisation avec 0.

0
bitmask 28 août 2020 à 11:05