记住变量以供下次使用

时间:2014-02-15 18:32:07

标签: c++ variables memory if-statement

我在记住下一次使用的变量并将其打印出来时遇到问题。我解释得更多,所以要理解我在我的计划中要做什么。

我有一个人走在一个大小为a b的矩形上。我输入起始位置x y和开始方向的人(北= y + 1,南= y-1,东= x + 1,西= x-1 //在我的代码中它是S,J,V ,Z)。所以我的输入如下:

5 6 // a b 3 3 S // x y s(这代表起始方向 - 北方)

现在,我输入要为其移动的人生成的移动次数d。 我输入数字4,它可以生成3个字母:D,L,P(向前,向左转90度,向右转90度)。

4 // d PLDL //移动

现在,这个人应该走这些动作。因此,如果人的位置和起始方向是3 3 S,它应该向右转(我的方向是东方但位置相同),然后向左(方向再次向北,同一位置),然后向前(现在我移动{{ 1}},我的方向仍然是北方),最后一步向左转(向西方向)。所以mi的最终位置和方向(输出)是:

y+1

希望你能理解。如果不清楚,请发表评论。

我现在得到奇怪的输出,不真实的数字。我无法弄清楚如何将变量和条件放在一起来解决它。我的代码首先是起始方向和位置,但是稍后当我生成移动时,它应该根据生成的字符串更改为最终输出。可悲的是,它没有像我期望的那样工作。你有什么建议吗?我的问题很广泛,但我希望我们可以一起解决。

3 4 Z

示例输入:

#include <iostream>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <vector>

using namespace std;
int n; // pocet uloh
int a; // rozmer obdlznika a
int b; // rozmer obdlznika b
int i;


static const char alpha[] = {'D', 'L', 'P'};
char genRandom()
{

    return alpha[rand() % strlen(alpha)];
}
// end of generator

// funkcia na pohyb

void pohyb (){
    int x[i];
    int y[i];
    string sD = ""; // starting direction
    string mD = ""; // middle direction (stored one for next use)
    string eD = ""; // ending direction to print out in output
    string d = ""; // number of generated directions eg. d=6 ==> PDDLPPD


    for (int i=0; i < d.size(); i++){

            if (sD[i] == 'S'){
                if(d[i] == 'D'){
                    y[i] = (y[i]+1);
                }else if(d[i] == 'L'){
                    mD[i] == 'Z'; 
                }else if(d[i] == 'P'){
                    mD[i] == 'V'; 
                }
            }else if (sD[i] == 'J'){
                if(d[i] == 'D'){    
                    y[i] = (y[i]-1);
                }else if(d[i] == 'L'){
                    mD[i] == 'V'; 
                }else if(d[i] == 'P'){
                    mD[i] == 'Z'; 
                }    
            }else if (sD[i] == 'V'){
                if(d[i] == 'D'){
                    x[i] = (x[i]+1);
                }else if(d[i] == 'L'){
                    mD[i] == 'S'; 
                }else if(d[i] == 'P'){
                    mD[i] == 'J'; 
                }    
            }else if (sD[i] == 'Z'){
                if(d[i] == 'D'){
                    x[i] = (x[i]-1);
                }else if(d[i] == 'L'){
                    mD[i] == 'J'; 
                }else if(d[i] == 'P'){
                    mD[i] == 'S'; 
                }    
            } // koniec if podmienky
    eD = mD[i];
    } // koniec for loopu
    // vystup
    for ( i = 0 ; i < n ; i++ )
    {

        if(!((x[i]>=0)&&(x[i]<=a) & (y[i]>=0)&&(y[i]<=b))){
            cout << x[i] << ' ' << y[i] << ' ' << eD[i] << ' ' << "SPADOL" << endl;
        }else{
            cout << x[i] << ' ' << y[i] << ' ' << eD[i] << endl;
        }

    } 

} // koniec funkcie pohyb



int main() {

    cin >> n;
    vector<int> x(n); // x position
    vector<int> y(n); // y position
    vector<int> d(n); // zombie directions generation ex. DPLDDP 
    vector<string> sD(n); // starting direction
    vector<string> eD(n); // ending direction

    while(!((n >= 1)&&(n <=15000)))
    {
        cout << "max 15000" << flush;
        cin >> n;
    }


    cin >> a >> b;

    while(!((a >= 1)&&(a <=100) & (b >= 1)&&(b <= 100)&&(a!=b)))
    {
        cout << "chyba max 100 alebo a!=b" << endl;
        cin >> a >> b;
    }


    for (i = 0; i < n; i++)
    {    
        cout << "Uloha " << i+1 << ":" << endl;
        cin >> x[i];
        cin >> y[i];
        cin >> sD[i];

        while(!((x[i]>=0)&&(x[i]<=a))) {
            cout << "Try Again x: " << flush;
            cin >> x[i];}
            while(!((y[i]>=0)&&(y[i]<=b))) {
                cout << "Try Again y: " << flush;
                cin >> y[i];}

                cin >> d[i];
                while(!((d[i]>=1)&& (d[i]<=200))) {
                    cout << "Try Again d: " << flush;
                    cin >> d[i];}


                    for (int counter=0; counter<d[i]; counter++)
                    {
                        cout << genRandom();
                    }
                    cout << endl;

    }    // koniec for

    pohyb();
system("pause");

}

和输出

3
3 5 
2 2 S 
8
DPLDLPDD
2 4 Z
7
PDDPDPD
2 1 J
8
PPDLDDDD

2 个答案:

答案 0 :(得分:4)

我不会修复您的代码,而是会给您一些解释,帮助您自己理解和修复它。

首先,让我调整您对变量的理解。在编程语言中,需要存储值。一旦我们存储了一个值,我们就需要能够再次检索它,因此我们需要一种方法来描述它的存储位置。

int i = 5;

这告诉编译器创建int值类型的实例,为其赋值5,并将其称为i

但是,C ++是一种范围内的语言。这意味着对任何给定名称的可见性存在限制。

int x() {
    int i;
}

int y() {
    i = 5; // ERROR: I not declared in this scope.
}

在上面的代码中,我们在一个范围内声明i - x的函数体 - 但后来尝试在另一个范围内使用它。

C ++范围通常以&#39; {...}&#39;来区分,例如以下内容有效:

#include <iostream>

int i = 0; // globally visible 'i'.

void f() { std::cout << "from f i = " << i << '\n'; }

int main() { // <-- function body scope
    int i = 1;
    { // inner scope
        int i = 2; // new variable, called 'i', but only inside this scope.
        { // <-- another inner scope
            i = 3;
            f();
        }
    } // scope ended, the second 'i' has no gone away.
    std::cout << "from end of main i = " << i << '\n';

    return 0;
}

以上程序打印&#34; 0&#34;然后&#34; 1&#34;。

C ++允许我们做一些调用&#34;阴影&#34; - 我们可以在不同的范围内为不同的变量使用相同的名称。

范围也会影响&#34;生命周期&#34;变量(见http://ideone.com/fXPlB7),但我不打算这样做。

让我更清楚地说明其含义 - 变量具有相似的名称但不是相同的变量:

int i = 5;

void f(float i)
{
    std::cout << "in f, i is " << i << '\n';
}

int main()
{
    char i[] = "Hello";

    f(3.141);

    std::cout << "in main, i is " << i << '\n';

    return 0;
}

该程序打印什么?

请确保您理解这一点: i 不会改变,而是在给定范围内<{1}}引用的变量

在您的函数i中,您有以下两行代码:

pohyb

这声明了一个新变量,在此范围内导致名称string d = ""; // number of generated directions eg. d=6 ==> PDDLPPD for (int i=0; i < d.size(); i++){ 引用它。 d是一个空字符串。

下一行迭代d中的所有值。空字符串中有多少个值?所以,for循环线说明了这一点:

d

0不是&lt; 0,所以循环永远不会执行。

您的下一个问题是字符串(C字符串)和字符数组之间的C ++差异。

C ++基于C,它没有&#34;字符串&#34;的第一类定义。相反,C有一个约定:&#34;字符串是一个包含0或更多字符的数组,后跟一个零值char&#34;。

int i = 0;
is i < 0?

处理&#34;字符串&#34;的所有C函数(不要与std :: strings混淆),按照这个原则操作 - 判断长度的唯一方法是计算字符,直到达到零值。

出于您的目的,您实际上想要一个字符数组,但这并不会自动使它们成为字符串。

您的代码使用char empty[1] = { 0 }; // valid, empty string. it has 1 element, the 'nul'. char a[] = { 'a', 0 }; // represents "a", size is 2 chars, 'a' and '\0' char hello[] = { 'h', 'e', 'l', 'l', 'o', 0 }; // size 6, 5 letters and a nul char Hello[] = "hello"; // short-cut for writing the above char ten[] = { '1', '0', 0 }; // '0' and 0 are not the same char hundred[] = { '1', '0', '\0' }; // '\0' == 0 char ouch[4] = "ouch"; // ERROR: the string is actually 5 chars. 来查找char数组中的元素数 - 这是不正确的,并且可能对您的应用程序造成危险。紧跟在strlen的3个有效元素之后的字节可以是任何内容,因此alpha可能返回3或者它可能返回非常大的值。

您真正想要的是C关键字strlen

sizeof是对事物大小的编译时确定。当X是完全限定数组时,它返回X的字节大小。请注意,这意味着您只能在全局或本地范围的数组中使用它:when you pass arrays to functions they are passed by pointer

sizeof(X)

您对输出的期望是什么?如果您想查找,请粘贴到ideone

对于您的代码,使用char数组看起来是正确的,因此您希望使用#include <iostream> char hello[] = "hello"; // has size 6: 'h', 'e', 'l', 'l', 'o', 0 void f(char x[]) { std::cout << "f(x), sizeof x = " << sizeof(x) << '\n'; } void g() { char x[] = "world"; std::cout << "g() sizeof x = " << sizeof(x) << '\n'; } void h() { int x[] = { 1, 2, 3, 4, 5, 6, 7 }; std::cout << "h() sizeof x = " << sizeof(x) << ", but sizeof(x[0]) = " << sizeof(x[0]) << '\n'; } int main() { std::cout << "main() sizeof hello = " << sizeof(hello) << '\n'; f(); g(); h(); return 0; } 来确定数组中有多少个字符。请记住,sizeof以字节为单位返回大小,正式正确的方式是:

sizeof

这将采用alpha的总大小并将其除以 alpha指向/包含(char)的大小。这些值在编译时是已知的,因此编译器将执行此计算并发出等效于:

的代码
size_t index = size_t(rand()) % (sizeof(alpha) / sizeof(*alpha))];
return alpha[index];

或只是

return alpha[rand() % (3 / 1)];

alpha中有3个元素,但C / C ++数组是0索引的,因此模数将为我们提供一个值[0,3],即0,1或2。

最后,您担心使用if语句。对于复杂的逻辑,有时最好的做法是将它们写出并通过手工运行。您可能希望熟悉return alpha[rand() % 3]; 关键字,该关键字采用变量并将其与潜在值匹配:

switch

http://ideone.com/s4xana

----编辑----

On&#34;记住&#34;范围之间的值。在函数体和嵌套范围内,这会自动发生:

#include <iostream>
#include <string>

int main()
{
    std::string input;

    while (std::cin.good()) {
        std::cout << "Direction? (n/s/e/w/q): ";
        std::getline(std::cin, input);

        // if input is empty, input[0] would be undefined behavior.
        if (input.empty())
            continue;

        switch (input[0]) // check the first character only
        {
            // input[0] is of type char, so we can express our values
            // a character literals. we could also write the ascii values,
            // e.g. for 'n' we could put "case 110:"
            case 'n':
                std::cout << "You have entered a dark room.\n";
                break; // escape the switch, not the loop.

            case 'e':
            case 's': // no break, 'e' falls thru
            case 'w': // still no break, 'e' and 's' fall thru
                std::cout << "You can't go that way.\n";
                break;

            case 'q':
                std::cout << "bye!\n";
                return 0;
                break;

            default:
                std::cout << "I asked you to type n, s, e, w or q, but you typed " << input << ".\n";
                break;
        }
    }

    return 0;
}

但是在函数和模块之间,你需要使它们成为函数参数。

int main() {
    int i = 1;
    { // inner scope
         std::cout << "inner scope\n";
         { // another inner scope
             if (i == 1) {
                 // this is a scope
                 std::cout << "i = " << i << '\n'; // prints 1
             }
         }
    }
}

这是什么印刷品?请记住:变量是本地范围的。仅仅因为它们与另一个范围内的另一个变量具有相同的名称并不会使它们连接起来。

考虑以下代码,警告:PSUEDO CODE:

#include <iostream>

int f(int i, int j, int k) {
    std::cout << "f() i = " << i << ", j = " << j << ", k = " << k << '\n';
    i = 10;
    j = 100;
    k = 300;
}

int main() {
    int j = 42;
    f(j, j, j);
    std::cout << "in main: j = " << j << '\n';
    return 0;
}

现在它可能更有意义 - 即使我们在define f - takes int as f::i, int as f::j, int as f::k "f() i = ", f::i, ", j = ", f::j, ", k = ", f::k, '\n'; f::i = 10; f::j = 100; f::k = 300; end f define main declare main::j as int let main::j be 42 call f with f::i = 42, f::j = 42 f::k = 42 "in main: j = " << main::j << '\n'; end main 中更改了j,它与我们在主要内容中看到的f不同。

如何克服这个问题:

C ++提供了两种方法。旧的,&#39; c&#39;方法是传递一个变量的地址,称为通过指针传递它。指针可能变得毛茸茸,常常让新程序员感到困惑,所以我会向你展示C ++机制:参考。

如上所述,当您使用参数调用函数时,C ++会创建一个新的本地范围变量,并将输入变量的值复制

j

我们在这里看到&#39; 5&#39;是不是变量,而是硬编码值。没有任何办法可以解决这个问题。否则可能会起作用 - 整个计划&#39; 5&#39;本来会变成7。

当我们想说&#34;调用f并操作我的LOCAL变量&#34;我们使用参考。

void f(int n)
{
    n += 2;
}

f(5);

很容易认为引用在某种程度上只是一个别名,但这并不是它们的实现方式。引用是一种巧妙的方法,可以在现有变量的内存中传递位置,但不够聪明,无法知道该变量消失或在内存中重新定位。

void f(int& n)
{
    n += 2;
}

int main()
{
    int x = 23;
    f(x);
    // x is now 25
}

关于引用要记住的另一件事是,一旦它们连接到某个东西,你就无法改变连接:

std::vector<int> v;
v.push_back(5);
int& first = v[0]; // reference to the first element of v at the moment,.
std::cout << "first = " << first << '\n'; // prints 5.
v.reserve(2000); // causes 'v' to relocate in memory
v[0] = 25;
std::cout << "first = " << first << '\n'; // may crash or print 5, but not 25.

这打印:566,而不是565,因为int a = 5, b = 6; int& r = a; std::cout << r; r = b; std::cout << r; std::cout << a; 使int& r = a引用了r。当我们说a时,因为r = b现在是r 的引用,我们有效地说a

----编辑2 ----

C和C ++有一个修饰符关键字a = b,这是一个合同,表示你保证不会修改某个东西。如果你想编写一个通过引用接受复杂对象的函数(以避免复制字符串等,这是昂贵的),但你不想改变它,你可以使用const修饰符:

const

另外,关于&#39;&amp;&#39;的说明。编译器是否写#include <iostream> #include <string> void writeln(const std::string& str) { std::cout << str << '\n'; } int main() { std::string greeting = "hello"; writeln(greeting); } string& str并不重要,它们的意思相同。 string &str是否意味着&#39;引用&#39;或者&#39;地址(用于指针)或&#39;和&#39; (对于逻辑)取决于上下文。

答案 1 :(得分:-1)

注意:这些是在您发布样本输入和输出之前编写的。

  1. alpha定义为

    static const char alpha[] = {'D', 'L', 'P'};
    

    它实际上是一个包含三个元素的char数组。但是strlen()是在遇到第一个\0(NUL)字符之前计算字符数的函数。因此strlen()中的genRandom()将无法正常工作(我猜它会返回一个随机的大数字。)您应该将alpha定义为

    static const char alpha[] = "DLP";
    

    将隐含的第4个元素\0添加到alpha

  2. 在您的pohyb()中,您使用空的初始值定义string varibales sDmDd。它们与vector<int> d中的vector<string> sD, mDmain()没有任何关系。因此,您的所有i < d.size()sD[i] == 'S'd[i] == 'D' ...都无法按预期工作。您应该将sD中的mDdmain()作为参数传递给pohyb()
    更新:好的我会更具体。由于string d中的pohyb()vector<int> d中的main()无关,pohyb()期间仍为空for (int i=0; i < d.size(); i++),因此int x[i], y[i]不会运行一次。因为pohyb()中的vector<int> x, ymain()中的i无关,并且包含未初始化(=随机)i元素(此处n恰好相同调用pohyb()到{{1}}时,您会看到奇怪的(“SPADOL”)输出。请先了解如何在C ++中将参数传递给函数。在你学习之前,你将无处可去。

  3. 我还没有检查这两个是否都是你需要的。它们只是我到目前为止发现的明显错误。您可能需要对程序结构进行基本的修改。