First of all, i need to say, that i am a complete noob.
I am trying to make some naval combat simulation to do that i created a random letter and number generator
Here's the code.
By the way, what i want to achieve is to have only one variable (Guess) to be confronted with the ship places that the user specified.
char letters[]= {'A','B','C','D','E','F','G','H','I','L'};
\\ lots of code
//RandomAI
int G = rand() % 10 + 1;
int nOut = rand() % 10 + 1;
char lOut = letters[G];
string Guess = lOut + nOut;
return 0;
string Guess = lOut + nOut; adds an int and char types which does not produce a std::string. One way to address this is to create a string and then append to it:
std::string guess = lOut + std::to_string(nOut);
This will solve your compiler error, but you still have a logic error here:
int G = rand() % 10 + 1;
rand() % 10 + 1 will produce a value between 1 and 10 inclusive. You want a number between 0 and 9 inclusive, because indices in C++ begin at 0, not 1. So drop the +1 portion:
int G = rand() % 10;
Otherwise you may accidentally attempt to access an out-of-bounds index in letters
Assuming you wanted an output string like 'A7' or 'F2', one way to achieved this would be to convert everything to string (since you can't add and int and a char). For those who don't have access to C++11 and std::to_string() yet, you could use:
char letters[]= {'A','B','C','D','E','F','G','H','I','L'};
int G = std::rand() % 10;
int nOut = std::rand() % 10;
char lOut = letters[G];
std::stringstream ss;
ss << nOut;
std::string Guess = lOut + ss.str();
Related
Since I am a newbie in this c++ programming. I kind a confuse with this question. If there is "const char str[]", How can I return this with integer value ??
for(int i=0; i<size; i++)
{
n = rand () % 98 + 1;
str [i] = n + '0';
}
Do I have to do str[i] = n -'0' ?
How can I return this character digit with integer value ??
First of all, if str is declared as a const char[] it means that the content of str is constant. Therefore you cannot modify it.
You could try to const_cast str, but it is usually a bad idea.
Secondly you can simply convert a char to an int by assigning your char variable to an intvariable.
char c = 'a';
int c_value = c;
You can find more inforation about const-correcteness here, and about type-casting here.
I'm kinda new on C++ and I'm having trouble on an exercise which is necessary to keep a name and the height of 10 people using structs.
The structs are:
typedef struct
{
char nome[50];
float altura;
} pserhumano;
typedef struct
{
float dia;
float mes;
float ano;
} dnasc;
And the functions are:
void CriaData(dnasc *D[], int i)
{
D[i]->mes = 1 + (rand() % 12);
D[i]->ano = 1950 + (rand() % 49);
D[i]->dia = 1 + (rand() % 30);
}
void InserirNome(pserhumano *Z[])
{
dnasc a[10];
for (int contador = 0; contador < 10; contador++) {
cout << "Insira o seu nome." << endl;
gets (Z[contador]->nome);
cout << "Insira a sua idade." << endl;
cin >> Z[contador]->altura;
CriaData(&a, contador);
}
}
This is the output on Ubuntu:
athos#ubuntu:~$ g++ exercicio1.cpp -w -o a
exercicio1.cpp: In function ‘void InserirNome(pserhumano**)’:
exercicio1.cpp:35:33: error: cannot convert ‘dnasc (*)[10]’ to ‘dnasc**’ for argument ‘1’ to ‘void CriaData(dnasc**, int)’
CriaData(&a, contador);
I'm having trouble to understand how to pass these arrays to the function. Any help is appreciated.
a is an array of dnasc
The function CriaData expects an array of pointers to dnasc
Change to :
void CriaData(dnasc D[], int i)
{
D[i].mes = 1 + (rand() % 12);
D[i].ano = 1950 + (rand() % 49);
D[i].dia = 1 + (rand() % 30);
}
And simply call:
CriaData(a, contador);
Notes:
Do not use gets, it is unsafe. Use std::cin
In your code you are using arrays, not vectors.
I'll go differently compared to the other answers. IMHO, What you really want is:
void CriaData(dnasc &D) {
D.mes = 1 + (rand() % 12);
D.ano = 1950 + (rand() % 49);
D.dia = 1 + (rand() % 30);
}
(i.e., Just to pass a dnasc object by reference).
and then in the loop just call:
dnasc a[10];
for(int contador = 0; contador < 10; ++i) {
...
CriaData(a[contador]);
}
No need to pass in the function useless subscripts etc.
Furthermore, if your compiler supports C++11 then you could use the new random number generation facilities. In this very nice talk Stephan T. Lavavej explains why you should not use rand() anymore.
The type of a in InserirNome is an array of 10 dnasc.
The type of &a is a pointer to an array of 10 dnasc. In C++, that is dnasc (*)[10].
This cannot be converted to dnasc**, which is the expected argument type of CriaData.
That's the compiler error message when you use
CriaData(&a, contador);
The following changes to CriaData should make it easier.
void CriaData(dnasc D[], int i)
{
D[i].mes = 1 + (rand() % 12);
D[i].ano = 1950 + (rand() % 49);
D[i].dia = 1 + (rand() % 30);
}
Then, you can call it using:
CriaData(a, contador);
The first parameter of function CriaData has type dnasc *D[] that is adjasted to type dnasc **D
void CriaData(dnasc *D[], int i)
But you call the function passing an expression of type dnasc( * )[10] that is you pass a pointer to local array dnasc a[10];
CriaData(&a, contador);
The correct function declaration would look as
void CriaData(dnasc D[], int i);
and the corresponding its call would look as
CriaData(a, contador);
Though I do not see a sense in calling this function for this local array.
I have a programming assignment where I need to encrypt a 4 digit int, input by user. I have split the int into four separate values and the encrypt and decrypt functions work. My problem is when I put the four separate ints back together, some numbers encrypt to zero (eg. in:1234 out:0189) and I want to store the output into an int for use with other functions.
Right now I have a half-baked solution that prints 0 first if the first int is 0.
void joinInt(){
if(int1 == 0) {cout << 0;}
joined = int1 * 1000;
joined += int2 * 100;
joined += int3 * 10;
joined += int4;
cout << joined << endl;
}
My goal is to return joined (with the leading zero) rather than just print it within the function.
Do this:
#include <iomanip>
#include <iostream>
std::cout << std::setfill('0') << std::setw(4) << joined << std::endl;
An int contains a number. It does not contain any particular representation information, like whether it was input from text containing one leading zero or two, or whether it was written in hexadecimal, octal, or chicken scratches, or even if it was computed from adding a bunch of numbers. It is just a value.
If you want to display an int with leading zeros, then you have to explicitly convert it that way:
char buf [20];
snprintf (buf, sizeof buf, "%04d", myint); // output base 10, + leading zeros
// for a field width of 4
An int basically stores leading zeros. The problem that you are running into is that you are not printing the leading zeros that are there.
Another, different approach is to create a function that will accept the four int values along with a string and to then return a string with the numbers.
With this approach you have a helper function with very good cohesion, no side effects, reusable where you need something similar to be done.
For instance:
char *joinedIntString (char *pBuff, int int1, int int2, int int3, int int4)
{
pBuff[0] = (int1 % 10) + '0';
pBuff[1] = (int2 % 10) + '0';
pBuff[2] = (int3 % 10) + '0';
pBuff[3] = (int4 % 10) + '0';
pBuff[4] = 0; // end of string needed.
return pBuff;
}
Then in the place where you need to print the value you can just call the function with the arguments and the provided character buffer and then just print the character buffer.
With this approach if you have some unreasonable numbers that end up have more than one leading zero, you will get all of the zeros.
Or you may want to have a function that combines the four ints into a single int and then another function that will print the combined int with leading zeros.
int createJoinedInt (int int1, int int2, int int3, int int4)
{
return (int1 % 10) * 1000 + (int2 % 10) * 100 + (int 3 % 10) * 10 + (int4 % 10);
}
char *joinedIntString (char *pBuff, int joinedInt)
{
pBuff[0] = ((joinedInt / 1000) % 10) + '0';
pBuff[1] = ((joinedInt / 100) % 10) + '0';
pBuff[2] = ((joinedInt / 10) % 10) + '0';
pBuff[3] = (joinedInt % 10) + '0';
pBuff[4] = 0; // end of string needed.
return pBuff;
}
This should do the trick.
cout << setw(4) << setfill('0') << joined << endl;
In order to use these manipulators, you'll need to:
#include <iomanip>
C++ stores int as a binary number. However all IO is as string. So, to display an int there must be a conversion from an int to a string. It's in the conversion process that you can set the with from the displayed number. Use the streams manipulators setw and setfill for this purpose.
Recently in an interview i was asked a question to write a function which takes two character arrays(integers) as input and returns the output character array.
Function Signature:
char* find_sum(char* a, char* b)
How would one approach this?
Example scenario:
find_sum("12345","32142") = "44487"
Note:
The number of digits can be many(1-100).
u can add huge numbers using the char array approach. however you need to delete the char* after using it every time or use some smart pointer.
char* find_sum(char* a, char* b) {
int lenA = strlen(a), lenB = strlen(b);
int max = lenA > lenB ? lenA : lenB; // Get the max for allocation
char* res = (char*)malloc (max+2);
memset(res, '0', max +1); // set the result to all zeros
res[max+1] = '\0';
int i=lenA - 1, j = lenB - 1, k = max;
for (; i >= 0 || j >=0; --i, --j, --k) {
int sum = 0;
if (i >= 0 && j>=0)
sum = a[i] - '0' + b[j] - '0' + res[k] - '0' ; // add using carry
else if (j >= 0)
sum = b[j] - '0' + res[k] - '0' ; // add the carry with remaining
else if (i >= 0)
sum = a[i] - '0' + res[k] - '0' ;
res[k] = sum % 10 + '0';
res[k-1] = sum / 10 + '0';
}
return res;
}
int main() {
printf (" sum = %s ", find_sum("12345432409240242342342342234234234", "9934563424242424242423442424234"));
return 0;
}
Note: The precondition for the function is the input char arrays should contain only numbers.
The most obvious answer is internally to use something like atoi and sprintf to convert the numbers to integers, do the sum and return the response as a char* However the important thing here is not what the interviewer is asking but why.
In my experience, the interviewer is probably not wanting you to write a hum-dinger of a solution that covers all angles. What they most likely want to get to is what the most common approach would be, and what are the likely limitations of such a function. I.e.:
What happens if your input numbers aren't integers? (e.g. 13.245, 2.3E+7)
What happens if your 'numbers' aren't numbers at all?
What happens if your input integers are really big? (i.e. ~2^31)
How could you detect an error and how would you report it.
How would you allocate memory for the resultant string?
What would the memory allocation imply for the calling code?
What is the efficiency of the function and how could you make it more efficient?
In this way, the interviewer wants to probe your experience of critiquing approaches to problem solving. Naturally, there are many ways of solving this problem. Some of the approaches have side-effects but in certain contexts, these side effects (i.e. integer overflow) may not be greatly important.
Coding is often a trade off between a comprehensive solution and what can be produced quickly (and therefore less expensively) These questions allow the interviewer to get a feel for your understanding of quality - that is, can you design something that is fit for purpose, robust and yet does not take too long to put together - and also your experience of having to identify / resolve common bugs.
You did not mention anything about not using any external command.
We can do this easily on machines that have the bc command. You can add any number of digits:
$ echo "99999999999999999999999999999999+1" | bc
100000000000000000000000000000000
$
We call this bc from the C program. We need to construct the right command line as
echo "n1+n2" | bc
and then use popen to read its result. Below is the function to do that. The code lacks many error checking.
char* find_sum(char* a, char* b) {
int l1 = strlen(a),l2 = strlen(b);
int cmdLen = l1 + l2 + 30; // 30 to accomodate echo,bc and stuff.
char *cmd = malloc(cmdLen);
snprintf(cmd,cmdLen,"echo \"%s+%s\"|bc",a,b);
FILE *fp = popen(cmd, "r");
int max = (l1 > l2) ? l1:l2;
max += 2; // one for additional digit, one for null.
char *result = malloc(max);
fgets(result, max, fp);
return result;
}
Working link
The answer is probably that you have to ask what is returned? Is this a memory allocated string that should be freed by the user or is this a static memory location that is overwritten the next time the function is called?
char* find_sum(char* a, char* b) {
static char buf[MAX_STRING];
...
return buf;
}
or
char* find_sum(char* a, char* b) {
char *buf = malloc(MAX_STRING*sizeof(char));
...
return buf;
}
Giving this answer shows the interviewer that you know more about C than just making an algorithm. (As a side-node: It also shows why a language like java shines in these situations as the garbage collections takes care of freeing the buffer).
Just remember how you did addition in the second grade on the paper.
#include <stdio.h>
#include <string.h>
char *sum(char *a,char *b);
int main()
{
char a[] = "100";
char b[] = "300";
char *c;
c = sum(a,b);
printf("%s",c);
}
char *sum(char *a,char *b)
{
int x,y,z,z2,zLen;
char *result;
x = atoi(a);
y = atoi(b);
z = x + y;
z2 = z;
/* Determine the length of the string now! */
for(zLen = 1; z > 0 || z < 0; zLen++)
z/=10;
result = (char *)malloc(zLen*sizeof(char)+1);
sprintf(result,"%d\0",z2);
return result;
}
Quick and dirty implimentation. Note that I'm not freeing the memory, which is not "ideal". Will fetch you extra brownie points for mentioning that there are no error checks happening here, and no freeing of memory, which is far from ideal in practical situations.
Online Version of Code
Several of the answers mention the use of atoi & itoa functions.
atoi returns int. Your numbers may not fit into an integer data type.
You may try to alleviate the problem (not completely though) using atol, which return a long int, or atoll, which returns a long long int.
Also, itoa is not a standard library function, and hence may not be available on all systems.
Here's another approach. Nothe that I don't like the prototype for find_sum. I'd very much prefer it to be
char *find_sum(char *dst, size_t len, const char *a, const char *b);
letting the caller be responsible for managing resources.
a and b are strings composed of 1 or more digits (and digits only); the result should be freed by caller. Calling find_sum with invalid inputs causes UB :-)
char *find_sum(char *a, char *b) {
char *res;
int alen, blen, rlen;
int carry;
alen = strlen(a);
blen = strlen(b);
rlen = 1 + ((alen > blen) ? alen : blen);
res = malloc(1 + rlen);
if (res) {
int oldlen = rlen;
res[rlen] = 0;
carry = 0;
while (rlen) {
int tmp;
if (alen && blen) tmp = a[--alen] - '0' + b[--blen] - '0';
else if (alen) tmp = a[--alen] - '0';
else if (blen) tmp = b[--blen] - '0';
else tmp = 0;
tmp += carry;
res[--rlen] = '0' + tmp % 10;
carry = tmp / 10;
}
if (res[0] == '0') memmove(res, res+1, oldlen);
}
return res;
}
There's a working version of the function at ideone ( http://ideone.com/O2jrx ).
itoa(atoi(a) + atoi(b), t, 10); if you want to be lazy, where t is a char[MAX_NUMBER_OF_DIGITS].
The real question regards the output array, as mentioned by other users.
Alright so i have two identical string methods...
string CreateCust() {
string nameArray[] ={"Tom","Timo","Sally","Kelly","Bob","Thomas","Samantha","Maria"};
int d = rand() % (8 - 1 + 1) + 1;
string e = nameArray[d];
return e;
}
string CreateFood() {
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
int d = rand() % (3 - 1 + 1) + 1;
string f = nameArray[d];
return f;
}
however no matter what i do it the guts of CreateFood it will always crash. i created a test chassis for it and it always fails at the cMeal = CreateFood();
Customer Cnow;
cout << "test1" << endl;
cMeal = Cnow.CreateFood();
cout << "test1" << endl;
cCustomer = Cnow.CreateCust();
cout << "test1" << endl;
i even switched CreateCust with CreateFood and it still fails at the CreateFood Function...
NOTE: if i make createFood a int method it does work...
Also guys even if i changed CreateFood to just COUT a message and nothing more it still crashed...
Take out the + 1 on both of them, you access arrays starting from 0:
int d = rand() % (8 - 1 + 1); // 0-7, not 1-8
int d = rand() % (3 - 1 + 1); // 0-2, not 1-3
Otherwise you're accessing a non-existent element, and this is undefined behavior. (That means it could appear to work, like in CreateCust, crash like in CreateFood, do nothing, or do anything.)
I'm not sure what the purpose of subtracting 1 then adding 1 is. In any case, now is the perfect time to learn: Don't Repeat Yourself. Even if you do something just twice, make a function out of it, it'll be less cryptic and more concise:
int random(int min, int max)
{
return rand() % ((b - a) + 1) + a;
}
This is a simple function that returns a random number between a and b, inclusive. (Means it can include both a and b in the results.) Now your code reads:
// I'll leave CreateCust up to you
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
int d = random(0, 2); // either 0, 1, or 2, randomly
string f = nameArray[d];
return f;
}
And you'll see even just one function makes it much easier to read; your goal is to make your code easy to read by humans. Also, this is much more concise:
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return nameArray[random(0, 2)];
}
Another bad thing to do is hardcode magic numbers into your program. For example, why 3 or 8? It can be deduced those are array sizes, but that doesn't stand on its own. What you might want is something like:
string CreateFood(void)
{
const size_t ArraySize = 3; // 3 elements, 0-2
string nameArray[ArraySize] = {"spagetti", "ChickenSoup", "Menudo"};
// ^ Ensure it matches
return nameArray[random(0, ArraySize - 1)];
}
Now the range for the number number makes sense up front.
The rest may be a bit advanced (which you won't understand until you get to templates), but shows how we might go on:
template <typename T, size_t N>
char (&countof_detail(T (&)[N]))[N];
#define countof(pX) sizeof(countof_detail(pX))
This nifty tool will give you the number of elements in an array. The code might turn into this
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
// ^ no explicit size
return nameArray[random(0, countof(nameArray) - 1)];
}
We got rid of any numbers altogether, you can just manipulate the array as you please. Lastly, we're repeating ourselves again: getting a random element from an array. We should make a function for that:
template <typename T, size_t N>
T& random_element(T (&pArray)[N])
{
return pArray[random(0, N - 1)];
}
This returns a random element from any array. Your function would then simply be:
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return random_element(nameArray);
}
Note in this refactoring (refactoring is taking code and factoring it into new, simpler parts) it reads much better: To get a food, we have an array of foods and we pick one at random.
Keep this kind of stuff in mind while you work, and as you learn C++ you can make better code. Anytime you repeat a task that isn't trivial, make it a function. Suddenly that task is trivial, because you don't care about how the function works (that's in the function), just what the function does (that's the function name).
The crash is happening because you are accessing an invalid index. This is because array indexes start from 0 and not 1, so you don't want to add a 1 to the rvalue of the modulus operator.
Here is a neat trick that you can use to make your code a little more maintainable:
template <class T>
T getRandElem( const T[] arr )
{
return arr[ rand() % ( sizeof(arr) / sizeof((arr)[0]) ) ];
}
string CreateCust(){
static string nameArray[] = {"Tom","Timo","Sally","Kelly","Bob","Thomas","Samantha","Maria"};
return getRandElem<string>( nameArray );
}
string CreateFood(){
static string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return getRandElem<string>( nameArray );
}
Look here:
int d = rand() % (8 - 1 + 1) + 1;
This will return a number between 1 and 8 inclusive. What you need is this:
int d = rand() % 8;
You're going outside the bounds of the array. The array object begins at 0.
I don't understand why you have
int d = rand() % (8 - 1 + 1) + 1;
Why not just use
int d = rand() % 8;
I think modern c++ compilers will still let you use an old C trick for static arrays:
string CreateFood()
{
char* nameArray = {"spagetti", "ChickenSoup", "Menudo"};
// note the trick to get the compiler to count the array elements for you:
int d = rand() % (sizeof(nameArray) / sizeof(nameArray[0]));
return std::string( nameArray[d] );
}