0

I'm making a simple console application that has a function that takes two arrays, one with a series of column widths, and the other a series of strings, and cout's each string then adds spaces until it reaches the next column.

I'm getting this error: error: expected primary-expression before 'int' at the first line of my columnizer function. I've tried changing the declaration in both the header and cpp file without success.

Here's the relevant code:

//cashier.cpp
void columnizer(int sizes[], std::string values[]){
    int columnCount = (sizeof sizes) / (sizeof int);

    for (int i=0; i < columnCount; i++){
        string value = values[i];
        cout << value;
        char valueLength = sizeof value / sizeof char
        char extraSpace = columnSizes[i] - valueLength;
        while (extraSpace > 0){
            cout << " ";
            extraSpace--;
        }
    }
}

The call to columnizer:

//cashier.cpp
int columnSizes[5] = {7, 15, 20, 9, 9};
string headers[5] = {"Qty","ISBN","Title","Price","Total"};
...
columnizer(columnSizes, headers);
...

Header file:

//cashier.h
int cashier();
void columnizer(int sizes[], std::string values[]);
Jpaji Rajnish
  • 1,491
  • 4
  • 17
  • 35
  • 2
    `char valueLength = sizeof value / sizeof char` <- missing semicolon – Andreas Grapentin Dec 08 '15 at 05:31
  • 2
    You do know that when an array is passed to a function it has decayed to a pointer to the first element in the array? Meaning that `sizeof` will give you the size of the *pointer* and not of the array. Either pass the size along as arguments to the functions, or use a container such as [`std::array`](http://en.cppreference.com/w/cpp/container/array). – Some programmer dude Dec 08 '15 at 05:33
  • 1
    `sizeof` also requires parentheses for type operands. – chris Dec 08 '15 at 05:33
  • What do you think `sizeof sizes` will do? (hint: `sizes` is not an array) – M.M Dec 08 '15 at 05:33
  • I didn't know arrays were decayed to pointers. Does that mean I have to explicitly jump memory addresses the size of the array contents in the for loop? Is there no more convenient way? – Jpaji Rajnish Dec 08 '15 at 05:36
  • 1
    Do not use arrays. Use `std::vector`. – n. m. could be an AI Dec 08 '15 at 05:39
  • For any array `a` and index `i`, the array indexing expression `a[i]` is equivalent to the pointer arithmetic expression `*(a + i)`, and it goes both ways. So you can still use array indexing even if you have pointers. The thing you need to change is (as I said before) to either pass the number of elements as an argument to the function, use a container, or [use templates to let the compiler deduce the size](http://stackoverflow.com/questions/3368883/how-does-this-size-of-array-template-function-work). – Some programmer dude Dec 08 '15 at 05:40
  • Thanks for pointer advice. This is getting a little sidetracked though. What does this error mean and why is it cropping up? – Jpaji Rajnish Dec 08 '15 at 05:50
  • I think I found the problem: When you use `sizeof` on a declaration type, you have to use parenthesis. – Jpaji Rajnish Dec 08 '15 at 05:54

1 Answers1

1

This code is riddled with problems:

  • what looks like argument arrays is actually turned into _pointers
  • there is a missing semicolon after one statement
  • the same statement is likely ill-advised: the length of a std::string s is determined using s.size()
  • names are used inconsistently

Here is an approach how you can patch up you code and avoid the obvious problems:

template <int N>
void columnizer(int (&sizes)[N], std::string (&values)[5]){
    for (int i=0; i < N; i++){
        std::string const& value = values[i];
        std::cout << value;
        char valueLength = value.size();
        char extraSpace = sizes[i] - valueLength;
        while (extraSpace > 0){
            std::cout << " ";
            extraSpace--;
        }
    }
}

The key magic is that you can pass references to arrays. Even more interesting, you can have the compiler deduce the size of arrays when passing them by reference, i.e., there is no need for the sizeof-hack. To make the deal even sweeter, the compiler will verify that the passed arrays are identical.

It seems you actually want to print column headers but your code actually doesn't print the column names. Note that you do not need to pad manually. You can, instead, set up the stream to pad with whitespace as needed, e.g.

std::cout << ' ' << std::setw(sizes[i]) << values[i];

You can use the manipulators std::left and std::right to put the output to the left or the right of any padding (you can also use std::internal to have the stream pad within the value, e.g. between the sign and value).

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • "This code is riddled with problems" - made me lol. Maybe my style is unprofessional but I like to write code fast and rough and take care of the missing semicolons in other parts after the more difficult problems. The error was in fact caused by not using parenthesis around `int` with the `sizeof` operator. Still your answer has good info in it and provides a practical solution so I'm giving this one to you :) – Jpaji Rajnish Dec 08 '15 at 10:07