Annoying Redundancies in C/C++

Pages: 12
So this is sort of a rant but also I want to know if anyone has some "secrets" they use to sort of fix up the problem. I've been coding in C/C++ for quite a while now, and I've begun to tackle more advanced stuff like graphics with SDL and whatnot. But more and more I despise the language for it's total un-elegance. Sure, it's the fastest, semi-low level language out there, and it really is super powerful. But I hate how un-compact it is. What do I mean? Well, here's a comparison between three different languages for the same program (note, I havn't run these so there might be errors but whatevs right?)

python:
1
2
3
  name = raw_input('What is your name? ')
  age  = int(raw_input('What is your age? '))
  print 'Your name is ' + name + ' and you are ' + age + ' years old.'


freeBasic:
1
2
3
4
5
  dim name as string
  dim age  as integer
  input "What is your age?",  age
  input "What is your name?", name
  print "Your name is "; name; " and you are "; age " years old."


C/C++:
1
2
3
4
5
6
7
8
9
  int main() {
    char name[99];
    int  age;
    print("What is your age? ");
    scanf("%i", &age);
    printf("What is your name? ");
    scanf("%s", name);
    printf("Your name is %s and you are %i years old.", name, age);
  }


Python is obviously the cleanest. The language is pretty bad, but it is atleast clean. Freebasic is also pretty clean. For all basic's quirks, it is fun to code in. Now look at C++. Just to get input I have to type two lines of code each time. Furthermore, the lines of code are almost the exact same both times. And the line lengths are all messy so you end up with "porcupine" code.

Now the question: How do you guys deal with this? It makes reading C++ code sorta hard since you have to split processes up onto so many lines, especially when many times you must repeat the same thing over and over again. I understand that I can create a function, but it seems so annoying to create a function just to combine two little processes like that.

Thanks,
-- Silas
That is plain C. C++ has streams too.
Create a function and use it every time.
raw_input in pyton is a function too.
C++ just doesn't have that function in standard libraries.
Define it once, place in some header and use it for very long time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class T>
void get_input(T& inp, std::string message)
{
    std::cout << message;
    std::cin >> inp;
}

int main()
{
    double foo;
    int bar;
    get_input(bar, "Enter your age: ");
    get_input(foo, "Enter your height\n");
    std::cout << "You are " << bar << " years old and " << foo << " tall";
}
Last edited on
ok thanks for the reply! That's kinda what I was thinking, but it seems annoying that I have to create extra functions just to get my code looking readable. I don't like having to make 1400000 little inline functions just to perform little 3 line actions.

Any other suggestions from you peeps? :D
You can put many statements on the same line in C++ if you like (I don't).
std::cout << "What is your age?"; std::cin >> age;

C++ is not always nice to look at but not all elegance is visual. I don't really see the issue with having a few extra lines. Having input and output separated makes sense. If you want to combine them in some way you can write a function to do so.

This is small "hello world"-programs. If you write something bigger you would use functions, classes, templates etc. so much of these kind of thing would be hidden away.
Last edited on
I understand what you are saying, and it is true to some degree. But my problem is that whenever I go to write something big, such as a game, I spend the first few days just writing the code that your other code readable. And if I don't do that, I have a function that initializes the screen or something that looks like a ginormous paragraph because of all the things I have to do over and over that aren't worth adding a function for.
What is it that you do over and over and why is it not worth adding a function? Example?
Last edited on
^^ and in such a way that you can copy/paste it from program to program.
Here's an example. This is from a game I was making and it is the setup function for the screen. Notice (1) how long some of the lines get and (2) how many of the code "sections" resemble each other but slightly different. For instance, setting up the window and checking if it's valid looks just like setting up the screen and checking if it's valid. Just slightly different function calls for each prevent them from becoming a single function though.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Screen::Screen(int _width, int _height, bool _is_fullscreen, std::string title) :
  is_fullscreen(_is_fullscreen), width(_width), height(_height), window(nullptr),
  renderer(nullptr), noise(nullptr), noise_interval(5), noise_res(64), noise_alpha(25) {

  srand(time(nullptr));

  if(SDL_Init(SDL_INIT_VIDEO) == -1)
    throw std::runtime_error(std::string("Error during video initialization. SDL 2.0 says: ") + SDL_GetError());

  window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN | (is_fullscreen * SDL_WINDOW_FULLSCREEN));
  if(window == nullptr)
    throw std::runtime_error(std::string("Error during window initialization. SDL 2.0 says: ") + SDL_GetError());

  renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  if(renderer == nullptr)
    throw std::runtime_error(std::string("Error during renderer initialization. SDL 2.0 says: ") + SDL_GetError());
  SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);

  SDL_Surface *noise_surface = SDL_CreateRGBSurface(0, noise_res + 64, noise_res + 64, 32, 0, 0, 0, 0xff);
  if(noise_surface == nullptr)
    throw std::runtime_error("Error generating snow.");
  Uint32 *p = (Uint32*)noise_surface->pixels;
  int max = (noise_res + 64) * (noise_res + 64);
  for(int i = 0; i < max; ++i, ++p) {
    int temp_color = rand() % 255;
    // for black and white noise *p = SDL_MapRGB(noise_surface->format, temp_color, temp_color, temp_color);
    *p = SDL_MapRGB(noise_surface->format, rand() % 255, rand() % 255, rand() % 255);
  }
  noise = SDL_CreateTextureFromSurface(renderer, noise_surface);
  SDL_FreeSurface(noise_surface);

  noise_rect  = {0, 0, noise_res, noise_res};
  noise_time = SDL_GetTicks();
}
I don't like having to make 1400000 little inline functions just to perform little 3 line actions.
The call to non-inline function is so much better and faster :)

Do not get me wrong. I like Python. It has neat syntax, is widely used and I think it is perfect language to start learnong programming from.
However each language have it's own area of use. C/C++ usually used for areas where speed is critical, so everything optimised for speed: arrays doen't do bounds checking, all standard collection have method which do ( at() ) and operator which doesn't ([]) do bounds checking, and so on. As all higher lever wrappers over primitive operations will slow down program execution there weren't much of them. Many widely used operation were added to the standard library lately, however. Looks like that function was not made it into standard yet. There might be something in BOOST, however...

The redundancy is cost of efficiency. If you look into assembly code, you will find so much redundancy... But no one complains. That is hifher level languages for you: hiding low-level manipulations from user.

BTW: this is part of what is called when you call raw_input()
(Code from CPython official implementation):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static char *
readline_until_enter_or_signal(char *prompt, int *signal)
{
    PyOS_sighandler_t old_inthandler;
    char *p;

    *signal = 0;

    old_inthandler = PyOS_setsig(SIGINT, onintr);
    if (setjmp(jbuf)) {
#ifdef HAVE_SIGRELSE
        /* This seems necessary on SunOS 4.1 (Rasmus Hahn) */
        sigrelse(SIGINT);
#endif
        PyOS_setsig(SIGINT, old_inthandler);
        *signal = 1;
        return NULL;
    }
    rl_event_hook = PyOS_InputHook;
    p = readline(prompt);
    PyOS_setsig(SIGINT, old_inthandler);

    return p;
}
There were two version, I took shortest
Last edited on
I actually despise most languages other than C/C++. I'm ok with Basic and Assembly. Javascript is fine for what it is meant for: basic web scripting. But python is super inefficient.

So basically what you are telling me is "deal with it buddy."

Oh, and btw I'm positive that the by nature, inline functions are faster for most situations that are only a few lines short. It actually inserts the function code into the spot where it is called, meaning the code doesn't have to change locations in memory to run it which is faster. For small stuff.
That is like with cars: manual transmission is cheaper and more effective if you know how to use it right. Automatic is more costly and inefficient but it is so easy to use...
> setting up the window and checking if it's valid looks just like setting up the screen and checking if it's valid.
> Just slightly different function calls for each prevent them from becoming a single function though.
But they are different things, ¿how do you expect to work with just one function?

However, you are coding in C.
By the way, your error handling is leaking resources.

1
2
3
4
5
6
SDL::Window window(/**/);
SDL::Renderer renderer(/**/); //in the initialization list

SDL::Surface noise_surface(/**/);
/*setting the values*/
noise.CreateFrom(noise_surface);

Invalid objects may throw an exception in their constructor, or they ignore their messages.
Also, the clean up code is handled in the destructor automagically.
You are comparing apples and oranges, but anyway, you should

never scanf("%s")

There. I said it.
Well I'm glad you all have sat around correcting my code and explaining to me that I am using C code. Why yes, I am, since all the C stuff still works in C++. Especially since the graphics API I am using is written in C, and not C++. So sorry ne555, my code is actually correct. They aren't objects, they are structures. So mine would be correct. There is no destructor for structures, so I have to throw errors and manually clean it up. I actually do know what I'm doing, I've been doing it for quite a while and I program in assembly a bit to so I actually understand what is going on.

I was asking if anybody had tips for cleaning up the formatting of the code and making it more readable while still allowing for maximum efficiency.
create some functions:
for example:
1
2
3
4
5
inline void check_result(bool x, std::string message)
{
    if (x)
        throw std::runtime_error(message);
}


Usage:
1
2
3
4
5
6
check_error(SDL_Init(SDL_INIT_VIDEO) == -1,
            std::string("Error during video initialization. SDL 2.0 says: ") + SDL_GetError()})
window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                          width, height, SDL_WINDOW_SHOWN | (is_fullscreen * SDL_WINDOW_FULLSCREEN));
check_error(!window,
            std::string("Error during window initialization. SDL 2.0 says: ") + SDL_GetError()})

(I had divided some lines so they won't be so long). If it isn't what do you want, show how you see it should be.
Last edited on
Well I'm glad you all have sat around correcting my code and explaining to me that I am using C code. Why yes, I am, since all the C stuff still works in C++.

The vast majority of C works with C++, but not all of it. And you made the distinction that C++ code was hard to read early in your posts. Not surprisingly, people are telling you that your code is written in a paradigm more suited to C. I wouldn't get in a huff about it. It's entirely true and entirely noteworthy.


They aren't objects, they are structures.

Well, if you were using C++ as you claim to be, instances of structures are objects. In fact there is no practical difference between an object which is described by struct or an object described by the class keyword. They are even capable of having destructors.


There is no destructor for structures, so I have to throw errors and manually clean it up. I actually do know what I'm doing, I've been doing it for quite a while and I program in assembly a bit to so I actually understand what is going on.

One needn't "manually clean it up" if one knows what one is doing. (And the contention was that you don't actually clean it up at all when an exception is thrown.) A simple RAII resource wrapper would simplify things greatly. Actually choosing a well-designed C++ library such as SFML over SDL would also be reasonable.
Last edited on
Well, you can use nicer formating:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Screen::Screen( int _width,
		int _height,
		bool _is_fullscreen,
		std::string title
		) :
		is_fullscreen(_is_fullscreen),
		width(_width),
		height(_height),
		window(nullptr),
		renderer(nullptr),
		noise(nullptr),
		noise_interval(5),
		noise_res(64),
		noise_alpha(25)
{

  srand(time(nullptr));

  if(SDL_Init(SDL_INIT_VIDEO) == -1)
    throw std::runtime_error(std::string("Error during video initialization. SDL 2.0 says: ")
						 + SDL_GetError()
						 );

  window = SDL_CreateWindow(title.c_str(),
				SDL_WINDOWPOS_CENTERED,
				SDL_WINDOWPOS_CENTERED,
				width, height,
				SDL_WINDOW_SHOWN |
				(is_fullscreen * SDL_WINDOW_FULLSCREEN)
				);

  if(window == nullptr)
    throw std::runtime_error(std::string("Error during window initialization. SDL 2.0 says: ")
							 + SDL_GetError()
							 );

  renderer = SDL_CreateRenderer(window,
				-1,
				SDL_RENDERER_ACCELERATED |
				SDL_RENDERER_PRESENTVSYNC
				);
  if(renderer == nullptr)
    throw std::runtime_error(std::string("Error during renderer initialization. SDL 2.0 says: ")
				 + SDL_GetError()
				 );

	SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);

  SDL_Surface *noise_surface = SDL_CreateRGBSurface(0,
					noise_res + 64,
					noise_res + 64,
					32, 0, 0, 0,
					0xff);
}


Or define macro's to make code cleaner.

ps. unfortunately, the page had some problems with \tabs ;). But you should know what i meant by this example
Last edited on
ps. unfortunately, the page had some problems with \tabs ;)


I think you mean "tabs have problems with displaying consistently"... which is why you shouldn't use them. ;P
Good rule: ident with tabs, align with spaces. That way code will look nice whatever tab size someone will set.
Pages: 12