Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re: Begginer's question: If loops one after the other. Is that code correct? (updated)

by haukex (Archbishop)
on Jan 10, 2017 at 14:01 UTC ( [id://1179309]=note: print w/replies, xml ) Need Help??


in reply to Begginer's question: If loops one after the other. Is that code correct?

Hi predrag,

Welcome to Perl and PerlMonks :-)

Just a note on terminology: Those things in braces are typically called "blocks" (Update 2: not everything in braces is a block, though, for example there are anonymous hashes). "Loops" are normally for/foreach, while, and until, each of which have their own "blocks". So what you've got there are three if/elsif/else structures, with a total of four blocks. (Update: See Compound Statements)

There's nothing obviously wrong with the code you showed. Whether or not it's "correct" depends on whether your program works or not :-)

The best way to know whether your program works or not is tests. That is, a set of test input data and an expected output to which you can compare the program's actual output (there are ways to automate this, but that's a different topic). In your tests, it's useful to test as many branches of your code as possible, by setting up your test input data so that as many of the if/elsif/else blocks as possible are executed.

Perhaps we could give you some more comments if you could show a slightly longer, more representative sample - for example, something that includes the outer foreach loop and some short example data that it operates on (see also SSCCE). This is just a wild guess since I don't know anything at all about the structure of your input data and what you're doing with it, but perhaps one of these two variants of the logic might be more appropriate:

if ($char eq "a") { ... } elsif ($char eq "b") { ... } if ($k==2) { ... } else { ... } # OR if ($char eq "a") { ... if ($k==2) { ... } else { ... } } elsif ($char eq "b") { ... }

Regards,
-- Hauke D

  • Comment on Re: Begginer's question: If loops one after the other. Is that code correct? (updated)
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: Begginer's question: If loops one after the other. Is that code correct? (updated)
by predrag (Scribe) on Jan 10, 2017 at 15:24 UTC

    Thanks a lot to everyone. I've already seen perlmonks as a friendly place but am really more then pleasantly surprised with so fast answers and warm welcome. Except Perl and a little bash scripting I wasn't in programming, only a long ago I've learned some Fortran but forgot a lot. So it was a prety strange for me to see that starting with Perl is not so difficult for a beginner as some people write on the web, but of course, I also see how Perl is complex and powerful. Anyway, I became addicted to do something in Perl everyday...

    I will remember terms and other suggestion, in any case will try to combine the first and last block as you suggested.

    I understand that nobody can help more seriously if there is not more of the code, but for the beginning, the most important for me was whether it is ok or not.

    The code I've sent is simplified because I wanted to concentrate just on one question. It is a part of the script of around 160 lines, that converts a html page from Serbian Latin to Cyrillic alphabet. That script works well, gives desired result (only for simple html pages). The task of these if blocs in foreach loop is to divide html code from the page content that will be converted. I know about Parser module and already installed and tried some simple examples but didn't know how it can help me in this case, so went back to my first solution.

    But, similar to my question in this node, although it gives good result, I would like to hear comments on that converter code, even if it is maybe ridiculous solution. I wonder what will be the most appropriate way for that - to start new node or in this one. The whole code could be probably be too much, so I could explain my approach only by words, or give some details of the code. I don't know anyone with whom I could talk about perl, so today is a big change for me.

      Hi predrag,

      It sounds like the trickiest part of your current solution is probably figuring out whether you're in some part of the HTML code or whether you're in the text, since obviously tags shouldn't be converted to Cyrillic. Unfortunately, parsing HTML is a pretty difficult task (a humorous post about the topic). So I'd like to encourage you to look at one of the parser modules again.

      Two classic modules are HTML::Parser and HTML::TreeBuilder, but there are several others, such as Mojo::DOM. If the input is always XHTML, there's XML::Twig and many more XML-based modules. These modules generally break down the HTML into their structure, including elements (<tags>) with their attributes, comments, or text. Some of the modules then represent the HTML as a Document Object Model (DOM), which is also worth reading a little about. It sounds like you only want to operate on text, and maybe on some elements' attributes (such as title="..." attributes).

      Operating only on text is relatively easy: for example, in a HTML::Parser solution, you could register a handler on the text event, which does the appropriate conversions, and register a default handler which just outputs everything else unchanged:

      use warnings; use strict; use HTML::Parser; my $p = HTML::Parser->new( api_version => 3, unbroken_text => 1 ); $p->handler(text => sub { my ($text) = @_; # ### Your filter here ### $text=~s/foo/bar/g; print $text; }, 'text'); $p->handler(default => sub { print shift; }, 'text'); my $infile = '/tmp/in.html'; my $outfile = '/tmp/out.html'; open my $out, '>', $outfile or die "open $outfile: $!"; # "select" redirects the "print"s my $previous = select $out; $p->parse_file($infile); close $out; select $previous; print "$infile -> $outfile\n";

      Operating on attributes will require you to handle opening elements (tags) as well. Note also that the same basic principle I described above applies to the other modules: they all break the HTML down into its components, so that you can operate on only the textual parts, leaving the others unchanged.

      BTW, have you seen Lingua::Translit?

      Hope this helps,
      -- Hauke D

        Thanks a lot Hauke D. Yes, it was my problem to resolve - position. No, I didn't know about Lingua::Translit

        When converting into Cyrilic, it is important to know that not all Cyrilic letters have one to one Latin letter correspondence, there are few that have two Latin letters correspondence.

        Oh, You already posted a code for converting with Parsel, thank you so much. I will save that code and try later. I would show my work although :) if for nothing else, it may be a fun for real programmers to look at it. I am maybe too cruel to my work. I resolved problem with html &nbsp also, so my script puts that into code and doesn't convert it.

        I think I have instaled HTML::TreeBuilder also. For now I work Perl in Virtual Machine where I have CentOS 6.7 and an old Ubuntu and I was pretty lucky to install modules in CentOS, I was a bit scared before. I have instaled Perl for Windows too

        Hauke D, I've tried your code with Parser module, works very well, thanks again. I understand the use of  s/foo/bar/g; now. It is a next important step for me, I am really encouraged to try different uses of that module on my site, as well as other modules you suggested. Maybe even for some simple search machines etc.

        It seems Parser doesn't work on non braking space

         <p>&nbsp;</p>

        but I think I can resolve that

      Hi predrag, can we use your first paragraph above in our advertising?

      Seriously, Perl is great, isn't it!

      You may have had a difficult time experimenting with Parser modules, but it's definitely the right approach. You may be surprised at how simple the code can be. Someone here has probably got experience and good advice for you.

      Do not worry about long code example, just use the <readmore></readmore> tags so you don't show it all. See Writeup Formatting Tips.

      Also make sure to post some sample input to your program and the output you desire for that input.

      edit: added link


      The way forward always starts with a minimal test.

        Thank you 1nickt. Of course, you can use that paragraph for Perl advertising and everything else from my posts.

        It was my real experience and I should add more: I am 57 years old now, I do have education in electronics, but it was long ago and I never worked in that field professionally. Maybe helped because I had a good approach to learn and practice Perl, through examples and many different tasks I've set to myself. When I have to realize my ideas I always divide task into many small parts, check everything, put counters in loops, print counters etc.

        Last winter, after finishing two Linux trainings I've asked my Linux teacher about a problem I could not resolve through bash scripting. He mentioned perl, pyhton, and ruby, but he wasn't so found of Perl. Somehow, I choose perl, although, I must admit, I didn't find many recommendations on the web. But as a very beginner I eventually wrote scripts for LZW encoding and decoding in Perl, not using modules. Of course, I've used some elements of the code from the web and did maybe a hundred different small examples and tests, but at the end I was successful. In that time, modules were too complicated to me, so I decided to go by my own foot. What was also surprising to me that I've understood with Perl I can do many things for myself that I never expected before I would even try.

        Regarding that my script for converting, I will send it in my next post. Should that be in a new node?

        p.s. to check are Cyrilic letters visible, just few љ, ц,п,ж,Ђ

        In the text are visibe but in code not, should show: $lj = "љ";

        use utf8; binmode(STDOUT, ":utf8"); use open ':encoding(utf8)'; # input/output default encoding will be # UTF-8 elsif (($str_char eq "l") && ($next eq "j")){ $lj = "&#1113;";

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1179309]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (3)
As of 2024-04-24 02:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found