在c++数组中移动字符串值的问题

Issue with shifting string values in array C++

本文关键字:问题 字符串 移动 c++ 数组      更新时间:2023-10-16

我知道这可能是我在冒险,但我对c++非常陌生,并且在编写这个程序时遇到了困难。总之,我有一个程序,就像一个简单的气象站。它提示用户输入一个名字和他们想要存储的天气历史记录的数量,从而设置数组的大小。之后,他们可以输入天气数据的值,打印当前数据,并打印历史数据。但是我遇到的问题是,当数组满了,用户想要输入更多的数据时,它应该简单地复制数组的所有值到左边,删除0点的第一个值,并在末尾放置新值。最奇怪的是,当我运行它并输入一个奇数数组大小,比如3或1,它工作得很好,它应该移动值。但是当我用数组值运行它的时候甚至是2或4它就崩溃了。我试着调试它,但无法找到错误所在。任何帮助吗?这太草率了,抱歉,但我也被迫在main中声明所有内容并创建指针。

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
void askName(string &weatherString){
int size = 0;
//Asks the user to input a name for weather statation
cout << "Please enter the name of the Weather Station, then press enter." <<       endl;
getline(cin, weatherString);
size = weatherString.length();          //gets tge length of the string just inputed
//loop is to limit the amount of characters the user can input
while (size >= 31) {
    cout << "The maximum characters allowed is 30, please try again.";
    cout << "Please enter the name of the Weather Station, then press enter." << endl;
    getline(cin, weatherString);
    size = weatherString.length();              //gets the amount of charaters from the string
}
}
void arraySize(int &i){
string myString;
loop:
while (cout << "How many histories would you like to store?" << endl && getline(cin, myString) &&
    !(stringstream(myString) >> i)) {
    cout << "That is an Invalid input, press enter to try again.n";
    cin.clear(); //clears invalid
    cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n'); //discards the 
}
if (i <= 0){
    cout << "Value needs to be greater than 0, try again." << endl;
    goto loop;
}
}
void printWelcome(string &weatherString){
//Once the weather station name is subbmitted it is then printed
cout << "nWelcome to The " + weatherString + " Weather Station" << endl;
}

int getTemperature(int &currenttemp, int &i, int temp[], int &n){
string myString;
cout << "n";
//Tells user to input temperature but checks to make sure it is a valid input
temploop:
    while (cout << "Please enter the current temperature (In degrees Fahrenheit), then press enter." << endl && getline(cin, myString) &&
        !(stringstream(myString) >> currenttemp)) {
        cout << "That is an Invalid input, press enter to try again.n";
        cin.clear(); //clears invalid
        cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n'); //discards the input
    }
    //If statements makes sure that the user input is in a reasonable range
    int maxtemp = 200;
    int mintemp = -100;
    if (currenttemp > maxtemp){
        cout << "You must have melted, try again." << endl;
        goto temploop;
    }
    else if (currenttemp < mintemp){
        cout << "You must be frozen, try again." << endl;
        goto temploop;
    }
    if (n < i){
    temp[n] = currenttemp;
    n++;
}
else{
    for (int s = 0; s < n; s++){
        temp[s] = temp[s + 1];
    }
    n = i - 1;
    temp[n] = currenttemp;
    n++;
}
return currenttemp;
}
void windFunction(int &currentWindspeed, string &windDirection, int &i, int wind[], string direction[], int &m, int &p){
string myString;
    //Asks the user to input windspeed but checks to see if the input is valid
windloop:
    while (cout << "Please enter the current wind speed (in MPH), then press enter." << endl && getline(cin, myString) &&
        !(stringstream(myString) >> currentWindspeed)) {
        cout << "That is an Invalid input, press enter to try again.n";
        cin.clear(); //clears input
        cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n'); //discards the input
    }
    //Checks to make sure the input is in a reasonable range or goes back to the loop
    int minwind = 0;
    int maxwind = 300;
    if (currentWindspeed > maxwind){
        cout << "You must have blown away, try again." << endl;
        goto windloop;
    }
    else if (currentWindspeed < minwind){
        cout << "No such thing as negative wind speed, try again." << endl;
        goto windloop;
    }
    //checks to verify that the string value has not been altered from default before placing into arrray
    if (m < i){
    wind[m] = currentWindspeed;
    m++;
}
else{
    for (int s = 0; s < m; s++){
        wind[s] = wind[s + 1];
    }
    m = i - 1;
    wind[m] = currentWindspeed;
    m++;
}
//Asks the user to input the current wind direction and stores it as windDirection. Checks to see if it is a valid input
while (cout << "Please enter the current wind direction in capital letters(N, NE, NW, S, SE, SW, E, W), then press enter." << endl &&
    getline(cin, windDirection) && windDirection != "N" && windDirection != "NE" && windDirection != "NW" && windDirection != "S"
    && windDirection != "SE" && windDirection != "SW" && windDirection != "E" && windDirection != "W"){
    cout << "That is an Invalid wind direction input, press enter to try again.n";
    cin.clear();
    cin.ignore();
}
if (p < i){
    direction[p] = windDirection;
    p++;
}
else{
    for (int s = 0; s < p; s++){
        direction[s] = direction[s + 1];
    }
    p = i - 1;
    direction[p] = windDirection;
    p++;
}
  }
//gets the complete weather input from user
void getWeather(int &currenttemp, string &windDirection, int &currentWindspeed, int temp[], int wind[], string direction[], int &i, 
int &n, int &m, int &p){
getTemperature(currenttemp, i, temp, n);
windFunction(currentWindspeed, windDirection, i, wind, direction, m, p);
 }
 void inputMenu(int &currenttemp, int &currentWindspeed, string &windDirection, string &weatherString, int temp[], int wind[], 
string direction[], int &i, int &n, int &m, int &p);
void printWeather(int &currenttemp, int &currentWindspeed, string &windDirection, string &weatherString, int temp[], int wind[], 
string direction[], int &i, int &n, int &m, int &p){
//allows user to print the current values for the weather station as long as it has already been inputed
if (currenttemp != NULL && currentWindspeed >= 0 && windDirection.length() != NULL){
    cout << "n";
    cout << "The " << weatherString << " " << "Weather Station" << endl;
    cout << "Current Temperature: " << currenttemp << " " << "Degrees Fahrenheit" << endl;
    cout << "Current Wind Speed: " << currentWindspeed << " MPH" << " " << windDirection << endl;
}
else{
    cout << "No data has been inputed yet, please input data then try again." << endl;
    inputMenu(currenttemp, currentWindspeed, windDirection, weatherString, temp, wind, direction, i, n, m, p);              //No data found so user is sent back to option screen
}
}
void printHistory(int &currenttemp, int &currentWindspeed, string &windDirection, string &weatherString, int temp[], int wind[],
string direction[], int &i, int &n, int &m, int &p){
//allows user to print the current values for the weather station as long as it has already been inputed
if (currenttemp != NULL && currentWindspeed >= 0 && windDirection.length() != NULL){
    cout << "n";
    cout << "Saved readings are printed newest to oldest" << endl;
    cout << "The " << weatherString << " " << "Weather Station:";
    for (int a = i - 1; a >= 0; a--){
        if (!direction[a].empty()){
            cout << "n";
            cout << "Current Temperature: " << temp[a] << " " << "Degrees Fahrenheit" << endl;
            cout << "Current Wind Speed: " << wind[a] << " MPH" << " " << direction[a] << endl;
        }
    }
}
else{
    cout << "No data has been inputed yet, please input data then try again." << endl;
    inputMenu(currenttemp, currentWindspeed, windDirection, weatherString, temp, wind, direction, i, n, m, p);              //No data found so user is sent back to option screen
}
    }
    void inputMenu(int &currenttemp, int &currentWindspeed, string &windDirection, string &weatherString, int temp[], int wind[], 
string direction[], int &i, int &n, int &m, int &p){
int finish = 0;
//Loop which asks the user for three options to pick from
while (finish == 0){
    cout << "nPlease select from the from the following number options and press enter:" << endl;
    cout << "1. To input a complete weather reading" << endl;
    cout << "2. To Print the current weather" << endl;
    cout << "3. To Print the weather history" << endl;
    cout << "4. To exit the program" << endl;
    cout << "n" << endl;
    cout << "Enter your choice here: ";
    cin >> finish;                                                  //takes input from user
    system("CLS");                                              //clears screen
    cin.clear();
    cin.ignore();
    //switch statement evaluates the user input to different cases
    switch (finish) {
    case 1:
        do {
            getWeather(currenttemp, windDirection, currentWindspeed, temp, wind, direction, i, n, m, p);        //function to get the input of a complete weather reading
            finish = 0;         //sends user back to while loop menu
            system("CLS");
        } while (finish == 1);
        break;
    case 2:
        do{
            system("CLS");
            printWeather(currenttemp, currentWindspeed, windDirection, weatherString, temp, wind, direction, i, n, m, p);
            finish = 0;         //sends user back to while loop menu
        } while (finish == 2);
        break;
    case 3:
        do{
            system("CLS");
            printHistory(currenttemp, currentWindspeed, windDirection, weatherString, temp, wind, direction, i, n, m, p);
            finish = 0;         //sends user back to while loop menu
        } while (finish == 3);
        break;
    case 4:         //exits the program
        do{
            //delete[temp];
            //delete[wind];
            //delete[direction];
            exit(0);
        } while (finish == 4);
        break;
    default:
        cout << "Please enter a correct value option." << endl;
        finish = 0;         //invalid input will send user to the option screen
    }
}
}
int main(){
string weatherString;
int currenttemp = NULL;
int currentWindspeed = NULL;
string windDirection;
int i;
int n = 0;
int m = 0;
int p = 0;
int* temp;
int* wind;
string* direction;

askName(weatherString);                 //runs function to ask for name of station
system("CLS");              //clears the screen
arraySize(i);
temp = new (nothrow) int[i];
wind = new (nothrow) int[i];
direction = new (nothrow)string[i];
system("CLS");
printWelcome(weatherString);                //Welcome message saying name of station
inputMenu(currenttemp, currentWindspeed, windDirection, weatherString, temp, wind, direction, i, n, m, p);              //text driven menu for user input choices
return 0;
}

你的复制算法中有一个错误,你有两个地方。

下面是其中一个:

for (int s = 0; s < n; s++){
    temp[s] = temp[s + 1];
}

n是数组的长度。当s = n-1(最后一次迭代)时,s+1将等于n,这超出了数组的边界。

我也会检查I而不是n,因为I应该是长度。

要修复此问题,请比较i-1而不是i。您需要在两个地方更改此设置。

for (int s = 0; s < i - 1; s++){
    temp[s] = temp[s + 1];
}

我不知道为什么它只在偶数数组长度上崩溃,也许与内存对齐有关(IE可能会为奇数长度分配),但访问和写入未分配的内存调用未定义的行为,所以任何响应都是合理的。