C ++ цикл пока не читает -1 из моего файла - PullRequest
0 голосов
/ 08 октября 2019

Я пишу программу, которая читает числа из файла .txt и выводит соответствующее количество звездочек (для четных целых) и знаков доллара (для нечетных целых). Например, 3 будет выводить $$$, а 2 - **. Программа работает нормально, за исключением случаев, когда она читает число -1. Другие отрицательные числа работают нормально, за исключением -1 по какой-то причине ..

Вот мой код:

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <Windows.h>

using namespace std;

int main()
{
int value, even, odd;
ifstream infile;
infile.open("lab6_input.txt");

while (infile >> value)
{
    if (value % 2 == 0)
        cout << string(abs(value), "*$"[value % 2]) << endl;
    else
        cout << string(abs(value), "*$"[value % 2]) << endl;
    value++;
}
infile.close();

system("pause");
return 0;
}

Вот мой вывод: https://imgur.com/a/favqrLv

Последнее число в выходных данных - это -1, но оно просто отображает пустое место.

Ответы [ 2 ]

0 голосов
/ 08 октября 2019

Проблема заключается здесь

"*$"[value % 2]

В C ++ результат оператора по модулю, примененный к отрицательному числу, отрицателен (ну, технически немного сложнее , чем это),Таким образом, когда value отрицательно, эта инструкция вызывает неопределенное поведение, обращаясь к массиву (строковому литералу) за пределами (один с индексом -1 ).

Вы можете решитьпроблема с принятием абсолютного значения value или результата, но вместо этого попробуйте написать бесплатную функцию, подобную приведенной ниже.

constexpr bool is_odd(int x)
{
    return x % 2;
}

Это лучше выразит намерение и поможет компилятору оптимизировать ваш код(см., например, здесь ), потому что это как если бы вы спрашивали

Скажите, если value делится на два (остаток от деления на2 - ноль) или не .

Что отличается от

Дайте мне остаток от деления value на 2


На связанной странице компилятора вы, возможно, заметили, что компиляторы в конечном итоге используют простую

and     edi, 1

вместо выполнения реальной операции по модулю. Это потому, что вам действительно нужен менее значимый бит, и вы можете напрямую использовать в своем коде

value & 1

Обратите внимание, однако, что Стандарт (C ++ 17, пока я пишу) не 't обязывает (пока C ++ 20 потребует дополнения до двух) конкретным двоичным представлением для типа int, поэтому предыдущий будет определен реализацией (и будет неправильным, если вы обнаружите ’s 'дополнение ). все еще работает int реализация).

0 голосов
/ 08 октября 2019

Ваш код кажется немного странным. Ваши переменные не инициализируются, четные и нечетные даже не используются. Ваше заявление if не нужно, потому что у вас в обоих случаях один и тот же код.

На ваш вопрос: вам следует использовать abs(value) дважды. Попробуйте

while(infile >> value){
cout << string(abs(value), "*$"[abs(value) % 2]) << endl;
value++;
}

Живой пример

...