I'm a beginner programmer and i'm confised. How can i compare many char variables?
So, i have in .in file smt like that:
n (an unsigned variable, like 7, how many char are down)
A B C C B D B
in .out file i must have which characters are repeated and how often repeat:
B 3
C 2
how can i do this? please help me. i think i can use a for and vectors... but how?
i tried somthing, but i don't know how to continue :( (litera mean character)
unsigned n,i;
char litera;
f>>n;
for (i=1;i<=n;i++)
f>>litera;
return 0;
use a counting array:
int array[256] = {};
unsigned int n,i;
char tmp;
f>>n;
for (i=1;i<=n;i++)
f>>tmp;
array[tmp] ++;
after that you can just print into the file all the values in the array that are not zero.
Simpler way is to use a std::map< char, int> that would store the count of each character.
unsigned n,i;
f>>n;
char ch;
std::map< char, int > myMap;
for (i=1;i<=n;i++) {
f>>ch;
if ( myMap[ch] )
myMap[ch]++;
else
myMap[ch] = 1;
}
Otherwise Use a vector of char.
unsigned n,i;
f>>n;
vector<char> litera( n );
for (i=1;i<=n;i++)
f>>litera[i];
For counting the number of repititions, there are many ways.
You can first sort the vector and iterate through the elements.
std::sort( litera.begin(), litera.end() );
int count = 1;
for ( int i = 0; i < litera.size(); i++ ) {
if ( litera[i] == litera[i+1] )
count++;
else if ( count > 1 ) {
std::cout << litera[i] << count << std:endl;
count = 0;
}
}
As number of possible chars is very limitted (256), you can define an array in size 255 which will represent how many instances of each chars exist.
Start by zeroing such an array. Then iterate your input characters and increment each cell you see. Finally print all non-zero element to output file.
I will not write the whole stuff for I guess you need/want to learn C++ and the best to do it is do stuff on your own. Here is idea, though.
Assuming you are reading ASCII characters only (as you are using char) I would declare a static array:
int counts[256] ;
and then filled it out initially with zeroes
You can use memset or a for loop to do that.
Next, when you read characters you increase specific cell of the counts array like that:
counts[litera]++ ;
At the end, when you are done reading, loop through the array and print out letter and corresponding number from the counts array:
for ( int i = 0 ; i < 256 ; i++ )
if ( counts[ i ] != 0 )
std::cout << static_cast< char >( i ) << " " << counts[ i ] << "\n" ;
I hope it will help.
Related
I have a following problem. I want to convert a string like "10 15 30" to an int array with ints 10, 15, 30. I searched in google a lot, but usually solutions included vectors (which I am not familiar with) or other more complex solutions. I found a code like this:
#include <cstdio>
void foo ( char *line ) {
int num, i = 0, len;
while ( sscanf( line, "%d%n", &num, &len) == 1 ) {
printf( "Number %d is %d; ", i, num );
line += len;
i++;
}
}
int main ( ) {
char test[] = "12 45 6 23 100";
foo( test );
return 0;
}
It works and extracts numbers from string in a way I wanted, but I don't understand part with:
line += len;
Can someone explain how it works? Why are we adding len (which is int) to the string?
Solution for C++:
#include <iostream>
#include <sstream>
#include <vector>
std::vector< int > foo ( char *c_str ) {
std::istringstream line( c_str );
std::vector< int > numbers;
for ( int n; line >> n; )
numbers.push_back( n );
return numbers;
}
int main ( ) {
char test[] = "12 45 6 23 100";
std::vector< int > numbers = foo( test );
for ( int n : numbers )
std::cout << n << ' ';
return 0;
}
Output:
12 45 6 23 100
%n specifies the number of characters accessed by sscanf in its one execution and saved it in variable len.
so line + =len; is incrementing variable line, with number of characters accessed by sscanf
line + =len; is nothing but line =line+ len;
line += len; is equivalent to line = line + len;
line is a char pointer, thus the code increases the pointer by len, so that the pointer points to the next number, every time the loop is executed. Note than len is updated by the call to sscanf().
The "string" is a pointer to a character buffer. You are performing pointer arithmetic to increment the sscanf to parse the next int characters from the buffer. So, in your example:
char test[] = "12 45 6 23 100";
say *line points to test, and has some pointer value, we don't care what the value is per-se, so let's say it is 1000. After the 1st call to sscanf, you read "12" in. That is two characters, so len should return 2. line then gets set to 1002, and is now "pointing" to the next set of characters in the buffer. sscanf reads that, and this continues until no more characters in the buffer.
Look at sscanf docs. It receive format and additional params.
In params you have "%d%n" which you explain using format table from docs.
d or u
Decimal integer
Any number of decimal digits (0-9), optionally preceded by a sign (+ or -). d is for a signed argument, and u for an unsigned.
n
Count
No input is consumed.
The number of characters read so far from stdin is stored in the pointed location.
So you read integer from string and number of chars this integer consist from.
After reading part of string you move pointer into number of read chars.
sscanf( line, "%d%n", &num, &len)
This line reads a number from line, and put the digit into num and number of characters read into len.
We need len to move pointer to unread portion of the string.
Does it make sense ?
Useful links:
scanf
sscanf
I want to save an integer type value in array.
Here is a code.
int a,arr[5];
cout<<"Enter a Number ";
cin >> a;
Suppose user enter the value 73972 This value save in arr like this.
arr[0] = 7;
arr[1] = 3;
.. .. .. ..
.. .. .. ..
arr[4] = 2;
How can I do that.???
Iterate reversely on the array and each time divide the number by 10 and store the reminder on the array.
for(int i=4; i>=0; i--)
{
arr[i] = a % 10;
a /= 10;
}
Read a string and break it into digits.
First of all integer values can have more than 5 digits.
You can get the number of digits that an object of type int can contain by using expression
std::numeric limits<int>::digits10 + 1
class std::numeric_limits is declared in header <limits>
Also take into account that if a number contains less digits than the size of the array then you need some mark that will determine the end of the number in the array.
I would advice you to use a character array instead of an array of integers in which the terminating zero will determine the end of the number.
If you want to use an integer array then the code could look the following way
#include <iostream>
#include <algorithm>
#include <limits>
int main()
{
int arr[std::numeric_limits<int>::digits10 + 1];
int a;
std::cout << "Enter a Number ";
std::cin >> a;
int n = 0;
do
{
arr[n++] = a % 10;
} while ( a /= 10 );
std::reverse( arr, arr + n );
for ( int i = 0; i < n; i++ ) std::cout << arr[i] << ' ';
std::cout << std::endl;
}
Use a single-subscripted array to solve the following problem: Read in 20 numbers, each of which is between 10 and 100, inclusive. As each number is read, print it only if it is not a duplicate of a number already read. Provide for the "worst case" in which all 20 numbers are different. Use the smallest possible array to solve this problem.
here is what I have so far:
#include <stdio.h>
#define SIZE 20
int duplicate (int num[] );
int main ()
{
int i, numbers[ SIZE ];
printf( " Enter 20 numbers between 10 and 100:\n " );
scanf_s( "%d\n" );
for (int i = 0; i < SIZE - 1; i++ );
{
int duplicate( int num[] )
{
int i, hold;
for ( i = 0; i <= SIZE - 1; i++ )
if ( num[i] == num[i=1] ){
hold = num[i];
else
hold = num[i+1];
}
printf( "%3d\n," num[ i ] );
}
Your professor is, unfortunately, probably not smart enough to solve his own problem. The smallest possible array for this problem is size 2 (Assuming a 64-bit data type, which is the largest the standard provides for. With 32-bit integers it would need three elements, and with 128-bit integers, just 1).
#include <stdint.h>
#include <stdio.h>
int main(void)
{
int_fast64_t visited[2] = { 0 };
int inputs_left = 20;
do {
int input, slot;
int_fast64_t mask;
puts("Enter an integer between 10 and 100: ");
if (!scanf("%d", &input)) {
puts("That's not a number!\n");
continue;
}
if (input < 10 || input > 100) {
puts("Out of range!\n");
continue;
}
slot = (input - 10) >> 6;
mask = 1 << ((input - 10) & 0x3F);
if (visited[slot] & mask) {
puts("Already seen, it is a duplicate.\n");
}
else {
visited[slot] |= mask;
printf("%d is new\n", input);
}
inputs_left--;
} while (inputs_left);
return 0;
}
You are welcome to use this code in your assignment, if you are able to correctly explain how it works (I hope your professor taught you how to write comments).
This is what I came up with, thanks for everybody's help:
#include <stdio.h>
#define MAX 20
int main()
{
int a[ MAX ] = { 0 }; /* user input */
int i; /* counter */
int j; /* counter */
int k = 0; /* number of integers entered */
int duplicate; /* notify of duplicates */
int value;
printf( "Enter 20 numbers between 10 - 100;\n" );
/* ask user for 20 numbers */
for ( i = 0; i <= MAX - 1; i++ ){
duplicate = 0;
scanf( "%d", &value);
/* decide if integer is duplicate */
for ( j = 0; j < k; j++ ) {
/* notify and stop loop if duplicate */
if ( value == a[ j ] ) {
duplicate = 1;
break;
{ /* end if */
/* enter number into array if it's not a duplicate */
if ( !duplicate )
a[ k++ ] = value;
} /* end if */
There are a few problems with your code:
The duplicate function is inside the main function.
i is declared multiple times
There should not be a semicolon after your first for loop.
The hold variable is not being used for anything. It is only being assigned a value.
num[i=1] - not sure what you are trying to do here, but the i=1 is setting i to 1.
In your first for loop, your condition is i < SIZE - 1, meaning it will loop 19 times, not 20. It should be i < SIZE or i <= SIZE - 1.
Your if statements should use braces ({}) for each if/else, or not at all.
if (test) {
// code
}
else {
// code
}
or
if (test)
// code
else
// code
As for the logic:
You are only getting one integer, which you are not putting in the numbers array. You will need to get 20 integers one by one and check the array each time the user enters a number.
The duplicate function should probably take a second parameter, the number that you want to check for. The if statement would check if num[i] equals the number you are looking for.
Remember to initialize the array values and only check values that you have set. For example, when the user enters the third number, you only want to check the first 2 numbers in the array to see if it already exists.
PS: Please try to indent your code properly. Many people will not even try to help if it is not indented properly.
My C is pretty rusty, so here's a pseudo-code solution (since this is homework you should do some of it for yourself):
print initial prompt;
declare nums[ array size 20 ]; // I later assume a 0-based index
declare boolean found;
for (i=0; i < 20; i++) {
// prompt for next number if desired
read next number into nums[i];
found = false;
// compare against all previously read numbers
for (j=0; j < i; j++) {
if (nums[j] == nums[i]) {
found = true;
break;
}
}
if (!found) {
print nums[i];
}
}
Note: the question as stated doesn't say the numbers have to be integers. Also, it says "use the smallest possible array" - you could do it with a 19 element array if you introduce a non-array variable for the current number (since the 20th number read only needs to be checked against the previous 19, not against itself), but that makes the code more complicated.
See also the comment I posted above that mentions some specific things wrong with your code. And check that all of your brackets match up.
I have a large hex string
abcdef...
and I want to convert it to
0xab 0xcd 0xef
Are there any functions that do that?
Also could you tell me what I means when people ask are those inputs in ASCII or not?
abcdef are represented as a string. Not sure if that is ASCII or not. not sure what they mean. I am very new to programming so help here would be appreciated. I have a huge string that I need to use in my array and converting it into the aforementioned format will help me initialize my array with the hex string.
You can do this using string streams.
#include <iostream>
#include <sstream>
#include <vector>
int main( int , char ** )
{
const char *str = "AFAB2591CFB70E77C7C417D8C389507A5";
const char *p1 = str;
const char *p2 = p1;
std::vector<unsigned short> output;
while( *p2 != NULL ) {
unsigned short byte;
++p2;
if( *p2 != NULL ) {
++p2;
}
std::stringstream sstm( std::string( p1, p2 ) );
sstm.flags( std::ios_base::hex );
sstm >> byte;
output.push_back( byte );
p1 += 2;
}
for( std::vector<unsigned short>::const_iterator it = output.begin(); it != output.end(); ++it ) {
std::cout << std::hex << std::showbase << *it << "\t" << std::dec << std::noshowbase << *it << "\n";
}
std::cout << "Press any key to continue ...";
std::cin.get();
}
Note that if you use unsigned char instead of unsigned short the conversion from stringstream attempts to convert it into an ASCII character and it doesn't work.
Read in each character one by one and convert it to a hex value (which is pretty easy).
You then need to, before reading the next number multiply the value by 16 (or, indeed, shift it left by 4) and read the next digit before adding it to the number you have so far. Keep going until you reach the end of your string.
When someone asks if they inputs are ASCII they are referring to whether your hex string is encoded using ASCII encoding. There are, equally various other encoding methods that range from the obsolete EBCDIC to the far more modern Unicode (which has different encodings which are still all unicode).
Bear in mind that the numbers 0 to 9, a to f and A to F have ASCII (or indeed unicode) values that are after one another in the encoding. So for numbers you can calculate its REAL value by doing "character - '0'". For 0 this will give you 0 and up to 9 it will give you 9 ...
the kit of parts you need in C is
for (..,i+=2)
and
strtoul(..,16)
Approximately the following (I wish I could made it shorter and use some library functions, any ideas?):
The function string_to_vector takes a character string and its length as input. It goes over the string, processing two characters (str[ i ] and str[ i + 1 ]) at a time. (For odd values of n, the last pass process only one character (str[ i ] though.) Each character is converted to numeric value using the hex_char_to_int method. Then it constructs a number by "joining" the two numeric values by shifting and adding. Finally, the constructed numeric value is appended to a vector of numeric values which is returned at the end of the function.
std::vector< unsigned >
string_to_vector( const char * str, size_t n ) {
std::vector< unsigned > result;
for( size_t i = 0; i < n; i += 2 ) {
unsigned number = hex_char_to_int( str[ i ] ); // most signifcnt nibble
if( (i + 1) < n ) {
unsigned lsn = hex_char_to_int( str[ i + 1 ] ); // least signt nibble
number = (number << 4) + lsn;
}
result.push_back( number );
}
return result;
}
The following function converts characters in the range [0-9A-Za-z] to the corresponding unsigned int value.
unsigned
hex_char_to_int( char c ) {
unsigned result = -1;
if( ('0' <= c) && (c <= '9') ) {
result = c - '0';
}
else if( ('A' <= c) && (c <= 'F') ) {
result = 10 + c - 'A';
}
else if( ('a' <= c) && (c <= 'f') ) {
result = 10 + c - 'a';
}
else {
assert( 0 );
}
return result;
}
I'm C++ begginer. I did this excercise from Deitel's book:
Use a one-dimensional array to solve
the following problem. Read in 20
numbers, each of which is between 10
and 100, inclusive. As each number is
read, validate it and store it in the
array only if it is not a duplicate of
a number already read. After reading
all the values, display only the
unique values that the user entered.
Provide for the "worst case" in which
all 20 numbers are different. Use the
smallest possible array to solve this
problem.
Here is my code:
#include <iostream>
using namespace std;
bool compare(int arrayNum[],int arraySize,int element);
int main()
{
const int size=20;
int i=1;
int num[size];
int arrayElement;
int counter=0;
while(i<=20)
{
cin>>arrayElement;
if(i==1) //stores first element in array
num[0]=arrayElement;
//compare new element with stored elements
//if element is not a duplicate store it in array
else if (compare(num,size,arrayElement))
{
counter++;
num[counter]=arrayElement;
}
i++;
}
//displays array elements
for(int k=0;k<=counter;k++)
cout<<num[k]<<endl;
return 0;
}
//compare elements in array
bool compare(int arrayNum[],int arraySize,int element)
{
for(int j=0;j<arraySize;j++)
{
if(arrayNum[j]==element)
return false;
}
return true;
}
It works, but I'm not sure if I have interpreted the task correctly. I assume then I don't have to include conditional statement for range of numbers (10 to 100 inclusive), as this will be read from the keyboard and input by me. Therefore why was this instruction included? Also at the end it says
use the smallest possible array
I assume the max size has to be 20,but I don't think there is a way to dynamically expand array size (for example while storing new elements) as array size is const. I would appreciate if someone could help me with this. Any comments regarding code, or better solution are welcome.
As each number is read, validate
it and store it in the array
Emphasis mine. The text clearly says that your program has to validate the input. In other words, it has to check that the entered number is between 10 and 100, and if it is not, handle the error appropriately. So yes, you do need a conditional, although exactly what you do to handle the error is up to you.
And you're right, since arrays aren't dynamically resizable, the array size has to be at least 20.
You do need a conditional. Basically it's saying to take in a number between 10 and 100. If it's not a number between those ranges, don't store it. Also, if that number already exists in the array, don't store it. Then just print out the values in the array.
You assume correct about the array size, it's maximum size would be 20, although you may not store all 20 values (again, because some input might be bad).
The smallest possible array is a char[12], where the individual bits are used as flags.
char data[12]; // memset(data, 0, sizeof(data)); in main();
void set(int n_raw;)
{
int n = n_raw - 10;
int index = n/8;
int offset = n-8*index;
data[index] |= 1 << offset; // added "1 <<"
}
Reading the values back is left as an exercise for the student.
I assume then I don't have to include
conditional statement for range of
numbers (10 to 100 inclusive), as this
will be read from the keyboard and
input by me. Therefore why was this
instruction included?
Sure, in this case you wrote the code and know to enter numbers within the range expected; however, it is a standard best-practice to always validate input data from a user, always. That way erroneous values are handled gracefully (with an appropriate error message) and helps to make your program more robust.
Also at the end it says
use the smallest possible array
I assume the max size has to be 20,,,
I think what they might have been getting at here is that you could have used an array of 91 bytes as shown below.
int cnt = 0; // count of unique values entered
byte values[91]; // values entered indicator array
int valIdx; // used as values array index
memset((void *)values, 0, sizeof(values)); // initialize array to all zeros
while ( cnt < 20 )
{
// [code for the following comments not shown]
// have user input a number
// validate the number (>= 10 && <= 100)
// subtract 10 from the number and store it in valIdx
// (now valIdx will contain a number >= 0 <= 90)
if ( !values[valIdx] )
{
values[valIdx] = 1;
++cnt;
}
}
// then to show the unique values...
for ( valIdx = 0; valIdx < sizeof(values); valIdx++ )
{
if ( values[valIdx] )
{
cout << valIdx + 10 << endl;
}
}
That solution however, would not have met the "use the smallest array possible" requirement.
Back to your code...
I would go ahead and add the user input validation, just for completeness (and to get into the habit of never trusting users (especially yourself).
As far as improvements go, here is one thing to think about. The compare routine goes through every array element when a unique number has been entered. It only needs to check against those that have a stored value in them. Making that change should lead you to refactor the contents of your while loop as well.
I'm studying C++ in the same book!!
My first implementation for solving this problem was one that don't use any complementar array.. it uses a linear search to find duplicates..
take a look:
#include <iostream>
using namespace std;
// remember: size_t = unsigned int
const size_t arraySize = 20;
size_t _array[ arraySize ];
// global variable to keep track of the last used
// position in the _array
size_t counter = 0;
// the argument is not changed, so pass it by
// const reference
bool dupSearch( const int & );
int main()
{
// disregard this
ios_base::sync_with_stdio( false );
// "temp" variable declared outside the loop to
// avoid repeated allocation and deallocation
int i = arraySize, temp;
// look at the loop condition below " ( i-- ) "
// remember:
// false = ( every expression evaluated to 0 )
// true = ( every expression evaluated to a non-zero result )
// more details on pag. 108 of the book. 8/e Portability tip 4.1
while ( i-- )
{
// read the number from the user
cin >> temp;
// if the number entered is valid, put the
// number on _array[ counter ] and increment 'counter'
if ( dupSearch( temp ))
{
_array[ counter ] = temp;
++counter;
}
}
// print the result in column format
cout << endl;
for ( size_t j = 0; j < counter; ++j )
cout << _array[ j ] << endl;
}
// validation: if the value is out of the described range, return false
// if is in the range, check for duplicates using linear search.
// if a duplicate is found, return false
// otherwise, return true.
bool dupSearch( const int &a )
{
if ( a < 10 || a > 100 )
return false;
else
for ( size_t i = 0; i < counter; ++i )
if ( _array[ i ] == a )
return false;
return true;
}
the number of comparisons is
n = ( n * ( n + 1 )) / 2
where n = counter. worst case --> counter = 20 numbers --> loop 210 times through the program execution.