1

I want to declare two types of variables in for's init-statement. like the following codes. I know "for (string word, int numb, ; cin>>word>>numb; )" is not working. just trying to let you know what I am trying to do. My goal is to declare two types of variables with the same lifetime and cin them together. Other way of coding is helpful too. thanks in advance.

#include <iostream>
#include <vector>
#include <string>
#include <utility>
using namespace std;
int main ()
{
    cout<<"enter a word and a number"<<endl;
    for (string word, int numb, ; cin>>word>>numb; )
    {
        //do some work      
    }
return 0;
}

ok, I think this is the closest I can get as someone suggested.

#include <iostream>
#include <vector>
#include <string>
#include <utility>
using namespace std;
int main ()
{
    vector<pair<string,int> > pvec;
    cout<<"enter a word and a number"<<endl;
    {
        int numb=0; 
        for (string word; cin>>word>>numb; )
            pvec.push_back(make_pair(word,numb));
    }
    cout<<pvec[3].second<<endl;
return 0;
} 
ihm
  • 1,763
  • 2
  • 17
  • 22
  • what isn't working? is it failing to compile? Is it compiling but giving incorrect results? – Nathan Fellman Nov 11 '11 at 21:14
  • for (string word, int numb, ; cin>>word>>numb; ) this statement. because "string" wants to declara int as a variable too. – ihm Nov 11 '11 at 21:17
  • 1
    In future posts please post **complete**, minimal sample programs. While your program is minimal, it is not complete. Why make all of us re-type the three missing header lines, instead of posting it yourself? See http://sscce.org for more information about complete, minimal sample programs. – Robᵩ Nov 11 '11 at 21:18
  • @Rob: Generally, I agree. In this instance, it's fairly clear (at least to me) that the above code is syntactically invalid, and the OP wants to know if such a thing is possible. – Oliver Charlesworth Nov 11 '11 at 21:19
  • Thanks, @OliCharlesworth. Even in this case, I was curious to see the exact error message -- which required more than a simple copy, paste, compile on my part. – Robᵩ Nov 11 '11 at 21:21
  • @OliCharlesworth yes, I am thinking if it's possible to do it – ihm Nov 11 '11 at 21:21
  • Thanks, @ihm. I find people get better and quicker answers if they take this particular first step. – Robᵩ Nov 11 '11 at 21:22
  • dup http://stackoverflow.com/questions/2687392/is-it-possible-to-declare-two-variables-of-different-types-in-a-for-loop – sdg Nov 11 '11 at 21:48

5 Answers5

6

This is not possible. You can declare two variables of the same basic type in the initialization statement in the for loop, but you cannot declare two variables of different basic types. You have to declare one outside of the for loop.

Nate
  • 11,467
  • 5
  • 42
  • 59
  • 1
    Actually he can declare a struct containing both of those variables – Erbureth says Reinstate Monica Nov 11 '11 at 21:22
  • 1
    He could, but is there really a reason to create a struct for two items that have nothing to do with each other? The right answer here is not to use a for loop, not to encourage questionable programming practice as a workaround to syntax. – Joel Nov 11 '11 at 21:26
  • That's declaring one variable of one type. Also, I find that notion offensive to the senses. If I ever saw a struct defined inside a for-loop initialization block in a code review, I would read the person who did it the riot act. – Nate Nov 11 '11 at 21:27
  • 1
    This is incorrect. `for (int a, *b, &c;...` has 3 different types. – Pubby Nov 11 '11 at 21:27
  • A rather classic use of `struct` (i.e. combining several variables together) if there ever was one. Personally I probably wouldn't do it, but I wouldn't complain either. – eq- Nov 11 '11 at 21:32
  • @Pubby Well played. I meant to say *basic* types. Corrected. – Nate Nov 11 '11 at 21:33
  • Right, I was just saying it is a possibility :) I would hate to see that too in the code. – Erbureth says Reinstate Monica Nov 11 '11 at 21:33
6

About the nearest you can get is:

int main ()
{
    cout<<"enter a word and a number"<<endl;
    {
        string word;
        for (int numb; cin>>word>>numb; )
        {
            //do some work      
        }
    }
    return 0;
}

The extra set of braces limits the scope of word similarly to the way the loop limits the scope of numb. Clearly, you could reverse the declarations; it might be better (more symmetric) to use:

int main ()
{
    cout<<"enter a word and a number"<<endl;
    {
        string word;
        int numb;
        while (cin>>word>>numb)
        {
            //do some work      
        }
    }
    return 0;
}

Since there is no increment or initialize operation, the code is really a while loop with a couple of declared variables; this achieves the same result and works.

Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
  • great. I think it's the closest one. it doesn't look clean, kinda bulky though. (not trying to be an @ss). just saying – ihm Nov 11 '11 at 21:35
3

I'm fairly certain it's not possible to declare 2 variables of 2 different types in a for statement, but I also fail to see the advantage to doing so over something like this:

int main ()
{
    cout<<"enter a word and a number"<<endl;
    while( cin.good() )
    {
        string word;
        int num;

        cin >> word >> num;
        //do some work      
    }
    return 0;
}

In general I prefer to use for loops where there is something to count or at least iterate over. Other situations should be using a while or do loop.

Joel
  • 5,508
  • 1
  • 18
  • 18
  • Your check is in the wrong place -- or you must have another. Your current code doesn't check whether the read operation was successful or not (and it's a *good* idiom to use stream operations as a condition). – eq- Nov 11 '11 at 21:28
  • It gets the idea across, I would claim. Especially as the OP asked about declaration syntax, not stream usage. – Joel Nov 11 '11 at 21:32
  • yes, this one works. but it doesn't look as clean as for loop. and this takes a lot space. – ihm Nov 11 '11 at 21:37
  • "Space taken" is a pretty awful measure for code readability, and has 0 to do with efficiency. – Joel Nov 14 '11 at 21:11
2

The way you are trying to do it is not the cleanest way. I'd do it like this:

string word;
int num;
while(true)
{
    cin >> word >> num;
    if (!cin.good()) break;
    // do some work
}

word and num are in the same scope (same "lifetime")

Note that you'd want to substitute the while(true) with some suitable condition.


If you want word and num to be inside the scope of the loop do something like:

while(true)
{
    string word;
    int num;
    cin >> word >> num;
    if (!cin.good()) break;
    // do some work
}

OR

{
    string word;
    int num;
    while(true)
    {
        cin >> word >> num;
        if (!cin.good()) break;
        // do some work
    }
}

I don't know why this would be necessary though.

jli
  • 6,274
  • 2
  • 25
  • 37
  • yes, this works, but word and num still exist after the while loop is over – ihm Nov 11 '11 at 21:22
  • If the OP's syntax were valid, it would arguably be cleaner; it would limit the scope of the variables to the loop. – Oliver Charlesworth Nov 11 '11 at 21:23
  • Then put them inside the scope of the loop. See my edit. Its stack allocation anyways. – jli Nov 11 '11 at 21:23
  • Now that's just stupid, refactoring a good test (i.e. stream operation's successfulness) out of the loop condition, and *not* testing the status of the stream at all. – eq- Nov 11 '11 at 21:30
  • @OliCharlesworth yes, I want to make it cleaner and easy to move around. – ihm Nov 11 '11 at 21:31
  • @jil, it's not checking cin status – ihm Nov 11 '11 at 21:32
  • @eq- @ihm Did you not see: "Note that you'd want to substitute the while(true) with some suitable condition." Meaning `cin.good()`, etc.. – jli Nov 11 '11 at 21:49
  • But you *can't* substitute while(true), the condition would be in the wrong place (i.e. before read operation). It's still in the wrong place in 1 of your examples. – eq- Nov 11 '11 at 22:03
1

The following is untested, but should work:

int main()
{
  std::cout << "enter a word and a number" << endl;
  for (struct { std::string word, int number } vars;
       std::cin >> vars.word >> vars.number;
      )
  {
    //do some work      
  }
  return 0;
}
celtschk
  • 18,046
  • 2
  • 34
  • 61
  • At least on VS 2010 it does not work. Although a quick look at the C++ grammar says it should be allowed, so maybe it's a bug in VS. edit: g++ allows it. – bames53 Nov 11 '11 at 21:41
  • 2
    Link to microsoft connect bug on this issue: https://connect.microsoft.com/VisualStudio/feedback/details/624410/visual-c-compiler-fails-to-parse-a-for-init-statement-that-starts-with-a-class-specifier – bames53 Nov 11 '11 at 21:49