Spliting letters from an input into an array in perl - arrays

I'm working on a project where I need to take an input from the user and then cut it up into its individual characters for later use (to shift them up one character) but I'm having trouble getting the input into an array and printing it out to check that its in there. Currently my code is
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my $count=0; # this block just creates variables
my $userinput;
print "Input?";
$userinput=<STDIN>; # this block just gets input and creates the array
my #userarray=();
while(<#userarray>) {
#userarray = split('', $userinput); #this block should loop as many times as there are characters in the input while separating the characters
}
print Dumper(#userarray); #this should print the array
My output should look some like this if their input is "house"
#userarray[0]= "h"
#userarray[1]= "o"
#userarray[2]= "u"
#userarray[3]= "s"
#userarray[4]= "e"
But when I do enter something in it just print back a blank screen despite strict and warnings not coming back with anything. Where did I go wrong?

<D> reads and returns one (the next) record (that's a line if the record separator $/ hasn't been changed) from the file handle D in scalar context. In list context all remaining records are returned (as an array).
Said that, this section is the problem:
$userinput=<STDIN>; # this block just gets input and creates the array
my #userarray=();
while(<#userarray>) {
#userarray = split('', $userinput); #this block should loop as many times as there are characters in the input while separating the characters
}
<#userarray> returns nothing as #userarray sure isn't a valid file handle. So that loop is never entered.
If you want the user to input only one line, don't use the loop at all. Read one line and split it.
$userinput=<STDIN>; # this block just gets input and creates the array
chomp($userinput);
my #userarray=();
#userarray = split('', $userinput);
But that loop may indicate, that you want the user to be able to enter more than one line. If so, loop until there's no input left (EOF), reading the input line by line. Split the line and push the result into your array.
while(my $line = <STDIN>) {
chomp($line);
push(#userarray, split('', $line));
print(join(',', #userarray) . "\n");
}
For both ways: chomp() removes the trailing record separator (new line) at the end of the record (line). Don't use it, if you want to keep these. I assumed you don't.

This is a common Perl pattern. You want to loop so the user can enter more data. Try something like this:
print "Input?";
while (my $userinput = <STDIN>) {
chomp $userinput; # remove trailing newline
my #userarray = split //, $userinput;
print Dumper(\#userarray);
}

Related

Bash echo of array element not showing up [duplicate]

This question already has answers here:
Bash: Split string into character array
(20 answers)
Closed 6 months ago.
I am reading a file that basically contains a list of binary data (fixed at 8 bits wide per line):
01011100
11110001
...
For each line that is read, I need to "remap" the bits in chunks of 4 bits to specific positions. So for example in the 1st line above, bits 1100 and 0101 will each be remapped that will follow this formula: bit 0 goes to bit 3 position, bit 1 to 2, bit 3 to 1, and lastly bit 2 to 0.
To do this, I coded as follows:
function remap {
echo "Remapper";
IFS=
read -ra din <<< $1;
echo ${#din};
echo ${din[1]};
## above line is just displaying blank as seen in below result
echo ${din[*]};
## do actual remapping here
};
for line in `cat $infile`;
do
data0=${line:0:4};
data1=${line:4:4};
echo "Read line";
echo $data0;
echo $data1;
remap $data0;
remap $data1;
done
I don't know why I'm not seeing the echoed array element. This is the output from the 1st read line:
Read line
0101
1100
Remapper
4
0101
Remapper
4
1100
I haven't gotten to coding the actual remapping itself because I couldn't even verify that I'm able to properly split the $1 variable of remap() function into the din array.
Thank you in advance for the help!
Unlike other languages, setting IFS to empty string does not split a string
into each character array. Instead you can use fold -w1 to
add a newline after each character:
remap() {
echo "Remapper"
mapfile -t din < <(fold -w1 <<< "$1")
echo "${din[3]}${din[2]}${din[0]}${din[1]}"
}
As it will be inefficient to invoke fold command every time, it
may be better to say:
remap() {
echo "Remapper"
echo "${1:3:1}${1:2:1}${1:0:1}${1:1:1}"
}
As a side note, you don't need to append semicolon after each command.
There are a number of confusions here. The biggest is that read -ra din is not splitting the string into characters. read will split its input into words delimited by the characters in IFS; normally that's whitespace, but since you set IFS to the empty string, there are no delimiters and the string won't be split at all. Anyway, you don't want to split it based on delimiters, you want to split it into characters, so read is the wrong tool.
Another source of confusion is that ${#din} isn't the length of the array, it's the length (in characters) of the first element of the array. ${#din[#]} would get the number of elements in the array, and in this case it'd be 1. More generally, declare -p din would be a better way to see what din is and what it contains; here, it'd print something like declare -a din='([0]="0101")', showing that it's an array with a single four-character element, numbered 0.
What I'd do here is skip trying to split the characters into array elements entirely, and just index them as characters in $1 -- that is, ${1:0:1} will get the first character (character #0) from $1, ${1:1:1} will get the second (#1), etc. So to print the bits in the order third, first, second, fourth, you'd use:
echo "${1:2:1}${1:0:1}${1:1:1}${1:3:1}"
Other recommendations: It's best to double-quote variable expansions (like I did above) to prevent weird parsing problems. for var in $(cat somefile) is a fragile way to read lines from a file; while read var; do ... done <somefile is generally better. I'd recommend remap() { instead of the nonstandard function remap { syntax, and semicolons are redundant at the end of lines (well... with a few weird exceptions). shellcheck.net will point most of these out, and is a good tool to sanity-check your scripts for common mistakes.

How can i read certain parts of of a text file and store them in character arrays to be compared?

here is the part of the program that i am struggling with, "You will need some kind of loop to read through the entries in a text file, for the 1st 4 fields in the text file, you will know that you are at the end of the field when you read a comma. For the last field in the text file, you will know you are at the end of the field when you read a newline.
I did the program using functions from string.h but was challenged do the same program without the use of string.h and i am stuck at the loop part of this program.
i know my loop is incorrect but i am having trouble figuring out the correct loop to use, any tips will be helpfully
do
{
ch = fgetc(fout);
if(ch == EOF)
{
break;
}
field[x]=ch;//loads all the characters into the array
printf("%c",field[x]);//printing
x++;
}while(1);//infinite loop
fclose(fout);
One way to solve this would be to make a 2dimensional array so a array of field and have an if in the loop that increments the variable that says which field array to use when there is a comma. You would end up with 5 char arrays that each have one field, and you'd have a \n in the last one Wich you then need to remove.
Hope this helps

I need to print out all of the words in the file that begin with an uppercase character

i need to access a file and from that file i need to print out all the words that starts with a capital letter and also how many times the words have occurred. for example in the file there is a text "the Program should Display Files and also Files"
now the output should be:
Text
Program
Display
Files(2)//This word is written two times
enter image description here
while (!feof(..)) is normally not a good idea, instead write
while (fgets(readLine,sizeof(readLine), fpointer) != NULL)
{
}
it seems ptr is superfluous in this context, if you want to check for words in the line you should move it forward in the line?
alt. use instead the runtime function strtok:
for (ptr = strtok(readLine, " "); ptr != NULL; ptr = strtok(NULL, " ")
{
// now ptr will point to each word in the line, then you just check
// if the first character is upper case.
}
This sounds like a homework assignment, so I am not going to put the code here. I can give you the steps to take to have a general idea:
Open and read the file
Use something like strtok to split the lines into words
Loop over the words and check the first character (remember that a word is an array of chars. You can check if it's in range of 60 - 95 as based on the ascii table.
To count words you can create a hashmap in which you store the word with a count as value e.g. {word1: 1, word2: 2}
In the end you go over all the keys in the hashmap and print the key + count.

C while loop until user enters "quit"

Here's my code:
1. User types in two names, with a space in between. This means that two strings need to be read. I.e. input:
John Doe.
The strings are then checked in a char-array. (works fine).
The while loop goes on until the user types "stop" - only "stop".
How can I make it to stop directly if "stop" is entered - without the need to check the second string?
The code:
while(bool==false)
{
scanf("%20s%20s", name1, name2);
if(strcmp(name1, "stop")==0)
{
break;
}
// but still the second name has to be entered
rest of code...
}
Thanks for any tips!
I suggest you use fgets to get the input, check for the "stop" string, and then use sscanf to parse the input.
You can put to use the regular expression character class support provided by scanf.
You could do:
scanf("%s%[^\n]s", name, temp);
Here, your first word is mandatory while second is optional.
When you input 2 words, your temp would have a leading space.
If you want to directly avoid it, you can do so by:
char *p = temp;
scanf("%s%[^\n]s", name, p++);
Here, you can later access your 2 words using name and p

Trying to understand context in arrays/list in Perl

I am trying to understand the context (array/list/scalar) in Perl.
I tried the following:
#array = qw (john bill george);
print #array;
print "\n";
#sorted = sort (array);
print #sorted;
Why does the print #array concats the quoted words? I need to print
"#array"; to print the list? I mean # signifies an array right?
So why are the quoted needed for print?
Why does the print #sorted; prints array? If it is treated as a
scalar shouldn't it print 3 which is the size of the array?
print #sorted prints "array" because you forgot the # in the previous line :P
Change sort(array) to sort(#array) and it will print "billgeorgejohn".
As for why does print #array concatenate the quoted words, first let's make sure we're on the same page regarding qw:
#array = qw(john bill george);
is equivalent to
#array = ("john", "bill", "george");
so you're getting an array of three elements. Next, see the documentation for print. Passing a list of stuff to print will print them all, in order, separated by whatever value $, (the output field separator) has at the time. The default is empty string.
So you could do:
$, = " ";
print #array;
to get "john bill george".
The function print takes a list of arguments and prints those arguments.
If you explicitly pass a list to print then I hope you're not surprised when it prints out the elements of that list without spaces between them.
print 'one', 'two', 'three'; # prints "onetwothree
Passing an array to print is exactly the same. The contents of the array are converted to a list and then passed to print;
my #array = qw(one two three);
print #array; # prints "onetwothree"
In both of those cases, print receives three arguments and prints those arguments with nothing separating them.
Actually, Perl uses the special variable $, to control what print outputs between its arguments. By default that's an empty string, but you can change it.
Now let's consider your other case.
my #array = qw(one two three);
print "#array"; # prints "one two three"
How many arguments does print get in this example? Well, it's just one, isn't it? It's a single double quoted string. And when Perl sees a double quoted string it expands any variables in the string. The result of that expansion is then passed to print which then prints it. So we need to find out how Perl expands arrays in double-quoted. That's defined in the perldata manual page.
Array Interpolation
Arrays and slices are interpolated into double-quoted strings by
joining the elements with the delimiter specified in the $" variable
($LIST_SEPARATOR if "use English;" is specified), space by default.
So, by default, Perl interpolates arrays into double-quoted strings by inserting spaces between the elements. you can change that behaviour by changing the value of $".
These two examples might look the same, but they are actually very different.

Resources