Я пытаюсь распечатать 1-999 в английском формате, используя слова.
Пример:
Ввод: 563
Выход: Five Hundred Sixty Three
Я сделал функцию для чисел от 1 до 9, от 10 до 19 и чисел, оканчивающихся на 0 до 99 (20, 30, 40, 50... 90), и у меня есть отдельная функция для 100.
У меня есть несколько функций, а затем одна main()
функция. В последней функции я вызвал все предыдущие функции. Кроме того, у меня нет возвращаемого значения для моих функций.
При запуске возникает ошибка:
сигнал: ошибка сегментации (дамп ядра)
Может кто-нибудь, пожалуйста, помогите мне исправить это? И объясните как это сделать?
Это мой код:
#include <iostream>
using namespace std;
string digit_name(int digit) {
// defines 1 through 9
if (digit == 1){
return "One ";
}
if (digit == 2){
return "Two ";
}
if (digit == 3){
return "Three ";
}
if (digit == 4){
return "Four ";
}
if (digit == 5){
return "Five ";
}
if (digit == 6){
return "Six ";
}
if (digit == 7){
return "Seven ";
}
if (digit == 8){
return "Eight ";
}
if (digit == 9){
return "Nine";
}
}
string teen_name(int number){
// defines 10 through 19
if (number == 10){
return "Ten ";
}
if (number == 11){
return "Eleven ";
}
if (number == 12){
return "Twelve ";
}
if (number == 13){
return "Thirteen ";
}
if (number == 14){
return "Fourteen";
}
if (number == 15){
return "Fifteen";
}
if (number == 16){
return "Sixteen";
}
if (number == 17){
return "Seventeen";
}
if (number == 18){
return "Eighteen";
}
if (number == 19){
return "Nineteen";
}
}
string teens_name (int number){
// defines 20 through 90 (20, 30, 40 ... 90)
if (number == 20){
return "Twenty ";
}
if (number == 30){
return "Thirty ";
}
if (number == 40){
return "Forty ";
}
if (number == 50){
return "Fifty ";
}
if (number == 60){
return "Sixty ";
}
if (number == 70){
return "Seventy ";
}
if (number == 80){
return "Eighty ";
}
if (number == 90){
return "Ninty ";
}
}
string hun_name (int number){
// defines 100
return "Hundred ";
}
string define (int number){
// defines what it will output based on the input of the user
// if 1 through 9, output the name (ex: One)
if (number > 0 && number < 9){
cout << digit_name(number);
}
// if 10 through 19, output name (ex: Seventeen)
if (number >> 9 && number << 20){
cout << teen_name(number);
}
// if number divides by 100, then it will print digit_name, then Hundred, and then the teens_name
if (number/100){
cout << digit_name(number) << "Hundered " << teens_name(number) << digit_name(number);
}
// if number divides by 10 evenly, then it is one of the teens (ex: Sixty)
if (number/10 == 0){
cout << teens_name(number);
}
// else, it is a number from 21-99, so it will print teens_name and then digit_name
else{
cout << teens_name(number) << digit_name(number);
}
}
// main function - approved by Ms. B
int main() {
int num;
cout << "Please enter a number from 1 - 999: ";
cin >> num;
define (num);
}
if (number >> 9 && number << 20)
не делает того, что вы думаете, и поэтому teen_name
не возвращает значение. Вы имели в виду >
и <
вместо этого?
Как правило, ошибка сегментации является признаком того, что вы обращаетесь к недопустимому адресу памяти. (Здесь это не так очевидно, потому что у вас есть функции, которые не возвращают строку, а код, принадлежащий реализации строки, обращается к недопустимой «объектной» памяти объекта, которого там нет.)
И нельзя не подчеркнуть замечание @PaulMcKenzie в достаточной степени: всегда компилируйте с -Wall (или /W4 с MSVC), а также разбирайтесь и исправьте все предупреждения, прежде чем представлять код кому-либо (нам, вашему учителю, вашему работодателю, всему миру).
Кроме того, такие функции, как digit_name
, можно записать в 4 строки кода, если вы просто использовали массив строк и немного математики.
если число делится на 100, то будет напечатано digit_name, затем Hundred, а затем teens_name -- Если ваша программа должна преобразовывать число в слова, к сожалению, ваш код не делает этого правильно. Это гораздо больше, чем просто взять число и передать его teens_name
и digit_name
. Возьмем простой случай 300
— я не вижу, где вы печатаете слово «три», когда дается 300
.
«У меня есть несколько функций» — но только одна из них актуальна, когда возникает ошибка seg. Который из? Можете ли вы исключить большинство других функций? Имейте в виду, что ваш вопрос должен помочь другим. минимальный воспроизводимый пример лучше подходит для этой цели, чем программа, которая «распечатывает 1-999 в английском формате, используя слова».
@PaulMcKenzie Спасибо за ваш комментарий. Как мне написать функцию digit_name в 4 строчки, объясните пожалуйста. И да, я забыл добавить #includ <string>
@Peter - Восстановите Монику - я не знал, что могу проверить свой код и что с ним не так, используя -Wall (ow /W4). Это мой первый год изучения C++, и я новичок в программировании.
@JaMiT Спасибо за комментарий. Я буду помнить, чтобы мой код был как можно меньше.
@KrishaPatel - посмотрите ответ, который вы приняли. Все строки находятся в одном массиве, и вы используете небольшой расчет, чтобы получить правильную строку.
Вы не проверяете, действительно ли пользователь вводит number
между 1..999. Таким образом, любое число за пределами этого диапазона приведет к сбою вашей логики.
Ваша функция define()
объявлена как возвращающая string
(кстати, вам не хватает #include <string>
), однако на самом деле она ничего return
не делает. На самом деле, у большинства ваших функций та же проблема, поскольку они объявлены как возвращающие string
, но не все пути их кода на самом деле ведут к оператору return
. Это неопределенное поведение.
Кроме того, define()
неправильно обрабатывает случаи, когда number >= 9
. 9 полностью пропускается, и вы вообще не делите многозначные числа, вы просто передаете целое number
как есть каждой функции, что затем приводит ваши функции к путям, в которых отсутствуют операторы return
, вызывая неопределенное поведение повсюду место.
Кроме того, define()
использует операторы битового сдвига >>
и <<
во втором операторе if
вместо использования операторов сравнения >
и <
. И он неправильно проверяет «делит на 10 равномерно» в своем 4-м операторе if
, ему нужно будет использовать оператор модуля %
, а не оператор деления /
. Однако есть лучший способ написать свои if
утверждения, не используя в них никакого деления.
С учетом сказанного попробуйте что-то еще вроде этого:
#include <iostream>
#include <string>
#include <limits>
using namespace std;
// defines 1 through 9
string digit_name(int number){
static const char* words[] = {
"One ",
"Two ",
"Three ",
"Four ",
"Five ",
"Six ",
"Seven ",
"Eight ",
"Nine "
};
return words[number-1];
}
// defines 11 through 19
string teen_name(int number){
static const char* words[] = {
"Eleven ",
"Twelve ",
"Thirteen ",
"Fourteen ",
"Fifteen ",
"Sixteen ",
"Seventeen ",
"Eighteen ",
"Nineteen "
};
return words[number-11];
}
// defines 10 through 90 (20, 30, 40 ... 90)
string tens_name (int number){
static const char* words[] = {
"Ten ",
"Twenty ",
"Thirty ",
"Forty ",
"Fifty ",
"Sixty ",
"Seventy ",
"Eighty ",
"Ninty "
};
return words[(number/10)-1];
}
// defines 100 through 900 (200, 300, 400 ... 900)
string hun_name (int number){
return digit_name(number / 100) + "Hundred ";
}
string define (int number){
// defines what it will output based on the input of the user
string result;
// if number divides by 100, then it is one of the hundreds (ex: Two Hundred)
if (number >= 100){
result += hun_name(number);
number %= 100;
}
// if number divides by 10...
if (number >= 10){
// if number is 11 through 19, output name (ex: Seventeen)
if (number > 10 && number < 20){
result += teen_name(number);
number = 0;
}
else{
// number is one of the tens (ex: Sixty)
result += tens_name(number);
number %= 10;
}
}
// if number is 1 through 9, output the name (ex: One)
if (number > 0){
result += digit_name(number);
}
return result;
}
// main function - approved by Ms. B
int main() {
int num;
do{
cout << "Please enter a number from 1 - 999: ";
if (cin >> num){
if ((num >= 1) && (num <= 999))
break;
}
else{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
cout << "Invalid input, try again!\n";
}
while (true);
cout << define(num);
}
В качестве альтернативы вы можете заставить каждую функцию вычислять свою собственную часть оригинала number
и выводить соответствующие слова, если они есть. Таким образом, define()
может просто безоговорочно вызывать все функции, и будут возвращены только соответствующие слова, например:
#include <iostream>
#include <string>
#include <limits>
using namespace std;
// defines 1 through 9
string digit_name(int number){
static const char* words[] = {
"One ",
"Two ",
"Three ",
"Four ",
"Five ",
"Six ",
"Seven ",
"Eight ",
"Nine "
};
// if number has 1 through 9, output the name (ex: One)
number %= 10;
if (number){
return words[number-1];
}
return "";
}
// defines 11 through 19
string teen_name(int number){
static const char* words[] = {
"Eleven ",
"Twelve ",
"Thirteen ",
"Fourteen ",
"Fifteen ",
"Sixteen ",
"Seventeen ",
"Eighteen ",
"Nineteen "
};
// if number has 11 through 19, output name (ex: Seventeen)
number %= 100;
if (number > 10 && number < 20){
return words[number-11];
}
return "":
}
// defines 10 through 90 (20, 30, 40 ... 90)
string tens_name (int number){
static const char* words[] = {
"Ten ",
"Twenty ",
"Thirty ",
"Forty ",
"Fifty ",
"Sixty ",
"Seventy ",
"Eighty ",
"Ninty "
};
// if number divides by 10 and is not a teen, then it is one of the tens (ex: Sixty)
number %= 100;
if (number && (number < 11 || number > 19)){
return words[(number/10)-1];
}
return "";
}
// defines 100 through 900 (200, 300, 400 ... 900)
string hun_name (int number){
// if number divides by 100, then it is one of the hundreds (ex: Two Hundred)
if (number >= 100) {
return digit_name(number / 100) + "Hundred ";
}
return "";
}
string define (int number){
// defines what it will output based on the input of the user
return hun_name(number) + tens_name(number) + teen_name(number) + digit_name(number);
}
// main function - approved by Ms. B
int main() {
int num;
do{
cout << "Please enter a number from 1 - 999: ";
if (cin >> num){
if ((num >= 1) && (num <= 999))
break;
}
else{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
cout << "Invalid input, try again!\n";
}
while (true);
cout << define(num);
}
Этот код определенно работает, но я еще не научился этому. Мы не использовали статику в классе, поэтому я до сих пор понятия не имею, что делаю, но ваше объяснение значительно облегчает понимание того, что я сделал неправильно. Спасибо вам большое за это.
Использование массивов (которые не обязательно должны быть статическими локальными, вместо этого они могут быть глобальными) просто делает функции более эффективными. Вместо этого вы можете так же легко вернуться к использованию операторов if
. Суть в том, чтобы разбить пользовательский number
на отдельные компоненты, а затем вывести соответствующие слова для каждого из них.
Я изменил свой код. Это то, что я получил сейчас:
#include <iostream>
#include <string>
using namespace std;
string digit_name(int digit) {
// defines 1 through 9
if (digit == 1){
return "One ";
}
if (digit == 2){
return "Two ";
}
if (digit == 3){
return "Three ";
}
if (digit == 4){
return "Four ";
}
if (digit == 5){
return "Five ";
}
if (digit == 6){
return "Six ";
}
if (digit == 7){
return "Seven ";
}
if (digit == 8){
return "Eight ";
}
if (digit == 9){
return "Nine";
}
return "";
}
string teen_name(int number){
// defines 10 through 19
if (number == 10){
return "Ten ";
}
if (number == 11){
return "Eleven ";
}
if (number == 12){
return "Twelve ";
}
if (number == 13){
return "Thirteen ";
}
if (number == 14){
return "Fourteen";
}
if (number == 15){
return "Fifteen";
}
if (number == 16){
return "Sixteen";
}
if (number == 17){
return "Seventeen";
}
if (number == 18){
return "Eighteen";
}
if (number == 19){
return "Nineteen";
}
return "";
}
string tens_name (int number){
// defines 20 through 90 (20, 30, 40 ... 90)
if (number >= 90){
return "Ninety ";
}
if (number >= 80){
return "Eighty ";
}
if (number >= 70){
return "Seventy ";
}
if (number >= 60){
return "Sixty ";
}
if (number >= 50){
return "Fifty ";
}
if (number >= 40){
return "Forty ";
}
if (number >= 30){
return "Thirty ";
}
if (number >= 20){
return "Twenty ";
}
return "";
}
// defines 100 through 900 (200, 300, 400 ... 900)
string hun_name (int number){
return digit_name(number / 100) + "Hundred ";
}
string define (int number){
// defines what it will output based on the input of the user
string result;
// if number divides by 100, then it is one of the hundreds (ex: Two Hundred)
if (number >= 100){
result += hun_name(number);
number %= 100;
}
// if number divides by 10...
if (number >= 10){
// if number is 11 through 19, output name (ex: Seventeen)
if (number > 10 && number < 20){
result += teen_name(number);
number = 0;
}
else{
// number is one of the tens (ex: Sixty)
result += tens_name(number);
number %= 10;
}
}
// if number is 1 through 9, output the name (ex: One)
if (number > 0){
result += digit_name(number);
}
return result;
}
// main function - approved by Ms. B
int main() {
int num;
cout << "Please enter a number: ";
cin >> num;
cout << define (num) << endl;
return 0;
}
1) Ты забыл
#include <string>
. 2) Вы игнорируете предупреждения компилятора? Вы объявили функции, которые возвращаютstd::string
, но не сдержали обещание возвращатьstd::string
во всех цепочках кода.